60 lines
1.6 KiB
Go
60 lines
1.6 KiB
Go
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
|
|
}
|