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