Skip to content

Commit

Permalink
feat(codec): add Debug() option
Browse files Browse the repository at this point in the history
  • Loading branch information
bounoable committed Jul 10, 2022
1 parent 1c2832d commit 2cc14cf
Showing 1 changed file with 53 additions and 12 deletions.
65 changes: 53 additions & 12 deletions codec/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package codec
import (
"encoding/json"
"fmt"
"log"
"reflect"
"sync"
)
Expand All @@ -23,10 +24,11 @@ type Registerer interface {
// Registry is a registry of data types. A Registry marshals and unmarshals
// event data and command payloads.
type Registry struct {
mux sync.RWMutex
factories map[string]func() any
fallbackMarshal func(any) ([]byte, error)
fallbackUnmarshal func([]byte, any) error
mux sync.RWMutex
factories map[string]func() any
defaultMarshal func(any) ([]byte, error)
defaultUnmarshal func([]byte, any) error
debug bool
}

// Marshaler can be implemented by data types to override the default marshaler.
Expand All @@ -51,17 +53,24 @@ func Default(marshal func(any) ([]byte, error), unmarshal func([]byte, any) erro
}

return func(r *Registry) {
r.fallbackMarshal = marshal
r.fallbackUnmarshal = unmarshal
r.defaultMarshal = marshal
r.defaultUnmarshal = unmarshal
}
}

// Debug returns an Option that configures the Registry to log debug information.
func Debug(debug bool) Option {
return func(r *Registry) {
r.debug = debug
}
}

// New returns a new Registry for encoding and decoding of event data or command payloads.
func New(opts ...Option) *Registry {
r := &Registry{
factories: make(map[string]func() any),
fallbackMarshal: json.Marshal,
fallbackUnmarshal: json.Unmarshal,
factories: make(map[string]func() any),
defaultMarshal: json.Marshal,
defaultUnmarshal: json.Unmarshal,
}
for _, opt := range opts {
opt(r)
Expand All @@ -78,6 +87,10 @@ func (r *Registry) Register(name string, factory func() any) {
r.mux.Lock()
defer r.mux.Unlock()
r.factories[name] = factory

if r.debug {
log.Printf("[goes/codec.Registry] registered type %T for name %q", resolve(factory()), name)
}
}

// New initializes the data type that is registered under the given name and
Expand All @@ -89,15 +102,30 @@ func (r *Registry) New(name string) (any, error) {
if !ok {
return nil, fmt.Errorf("no data type registered for name %q", name)
}

v := f()
if r.debug {
log.Printf("[goes/codec.Registry@New] initialized type %T (%s)", v, name)
}

return f(), nil
}

// Marshal marshals the provided data to a byte slice.
func (r *Registry) Marshal(data any) ([]byte, error) {
if m, ok := data.(Marshaler); ok {
if r.debug {
log.Printf("[goes/codec.Registry@Marshal] marshaling type %T using custom Marshaler", data)
}

return m.Marshal()
}
return r.fallbackMarshal(data)

if r.debug {
log.Printf("[goes/codec.Registry@Marshal] marshaling type %T using default marshaler", data)
}

return r.defaultMarshal(data)
}

// Unmarshal unmarshals the provided bytes to the data type that is registered
Expand All @@ -111,13 +139,22 @@ func (r *Registry) Unmarshal(b []byte, name string) (any, error) {
ptr := f()

if m, ok := ptr.(Unmarshaler); ok {
if r.debug {
log.Printf("[goes/codec.Registry@Unmarshal] unmarshaling type %T (%s) using custom Unmarshaler", resolve(ptr), name)
}

if err := m.Unmarshal(b); err != nil {
return nil, err
}

return resolve(ptr), nil
}

if err := r.fallbackUnmarshal(b, ptr); err != nil {
if r.debug {
log.Printf("[goes/codec.Registry@Unmarshal] unmarshaling type %T (%q) using default unmarshaler", resolve(ptr), name)
}

if err := r.defaultUnmarshal(b, ptr); err != nil {
return resolve(ptr), err
}

Expand All @@ -126,7 +163,11 @@ func (r *Registry) Unmarshal(b []byte, name string) (any, error) {

// resolves a pointer to the underlying data type.
func resolve(p any) any {
return reflect.ValueOf(p).Elem().Interface()
rv := reflect.ValueOf(p)
for rv.Kind() == reflect.Pointer {
rv = rv.Elem()
}
return rv.Interface()
}

// Register registers the generic data type under the given name.
Expand Down

0 comments on commit 2cc14cf

Please sign in to comment.