package builder import ( "reflect" "sync" ) var ( registry = make(map[reflect.Type]reflect.Type) registryMux sync.RWMutex ) // RegisterType maps the given builderType to a structType. // This mapping affects the type of slices returned by Get and is required for // GetStruct to work. // // Returns a Value containing an empty instance of the registered builderType. // // RegisterType will panic if builderType's underlying type is not Builder or // if structType's Kind is not Struct. func RegisterType(builderType reflect.Type, structType reflect.Type) *reflect.Value { registryMux.Lock() defer registryMux.Unlock() structType.NumField() // Panic if structType is not a struct registry[builderType] = structType emptyValue := emptyBuilderValue.Convert(builderType) return &emptyValue } // Register wraps RegisterType, taking instances instead of Types. // // Returns an empty instance of the registered builder type which can be used // as the initial value for builder expressions. See example. func Register(builderProto, structProto interface{}) interface{} { empty := RegisterType( reflect.TypeOf(builderProto), reflect.TypeOf(structProto), ).Interface() return empty } func getBuilderStructType(builderType reflect.Type) *reflect.Type { registryMux.RLock() defer registryMux.RUnlock() structType, ok := registry[builderType] if !ok { return nil } return &structType } func newBuilderStruct(builderType reflect.Type) *reflect.Value { structType := getBuilderStructType(builderType) if structType == nil { return nil } newStruct := reflect.New(*structType).Elem() return &newStruct }