github.com/aacfactory/avro@v1.2.12/internal/base/resolver.go (about)

     1  package base
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/modern-go/reflect2"
    10  )
    11  
    12  // TypeResolver resolves types by name.
    13  type TypeResolver struct {
    14  	names sync.Map // map[string]reflect2.Type
    15  	types sync.Map // map[int][]string
    16  }
    17  
    18  // NewTypeResolver creates a new type resolver with all primitive types
    19  // registered.
    20  func NewTypeResolver() *TypeResolver {
    21  	r := &TypeResolver{}
    22  
    23  	// Register basic types
    24  	r.Register(string(Null), &null{})
    25  	r.Register(string(Int), int8(0))
    26  	r.Register(string(Int), int16(0))
    27  	r.Register(string(Int), int32(0))
    28  	r.Register(string(Int), int(0))
    29  	r.Register(string(Long), int64(0))
    30  	r.Register(string(Float), float32(0))
    31  	r.Register(string(Double), float64(0))
    32  	r.Register(string(String), "")
    33  	r.Register(string(Bytes), []byte{})
    34  	r.Register(string(Boolean), true)
    35  
    36  	// Register logical types
    37  	r.Register(string(Int)+"."+string(Date), time.Time{})
    38  	r.Register(string(Int)+"."+string(TimeMillis), time.Duration(0))
    39  	r.Register(string(Long)+"."+string(TimestampMillis), time.Time{})
    40  	r.Register(string(Long)+"."+string(TimestampMicros), time.Time{})
    41  	r.Register(string(Long)+"."+string(TimeMicros), time.Duration(0))
    42  	r.Register(string(Bytes)+"."+string(Decimal), big.NewRat(1, 1))
    43  	r.Register(string(String)+"."+string(UUID), "")
    44  
    45  	return r
    46  }
    47  
    48  // Register registers names to their types for resolution.
    49  func (r *TypeResolver) Register(name string, obj any) {
    50  	typ := reflect2.TypeOf(obj)
    51  	rtype := typ.RType()
    52  
    53  	r.names.Store(name, typ)
    54  
    55  	raw, ok := r.types.LoadOrStore(rtype, []string{name})
    56  	if !ok {
    57  		return
    58  	}
    59  	names := raw.([]string)
    60  	names = append(names, name)
    61  	r.types.Store(rtype, names)
    62  }
    63  
    64  // Name gets the name for a type, or an error.
    65  func (r *TypeResolver) Name(typ reflect2.Type) ([]string, error) {
    66  	rtype := typ.RType()
    67  
    68  	names, ok := r.types.Load(rtype)
    69  	if !ok {
    70  		return nil, fmt.Errorf("avro: unable to resolve type %s", typ.String())
    71  	}
    72  
    73  	return names.([]string), nil
    74  }
    75  
    76  // Type gets the type for a name, or an error.
    77  func (r *TypeResolver) Type(name string) (reflect2.Type, error) {
    78  	typ, ok := r.names.Load(name)
    79  	if !ok {
    80  		return nil, fmt.Errorf("avro: unable to resolve type with name %s", name)
    81  	}
    82  
    83  	return typ.(reflect2.Type), nil
    84  }
    85  
    86  // Register registers names to their types for resolution. All primitive types are pre-registered.
    87  func Register(name string, obj any) {
    88  	DefaultConfig.Register(name, obj)
    89  }