summaryrefslogtreecommitdiff
path: root/vendor/github.com/lann/builder/registry.go
blob: 612845418e297ab5f1f8421b1d422846e51cefb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
}