source: code/trunk/vendor/git.sr.ht/~sircmpwn/go-bare/unions.go@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 1.9 KB
Line 
1package bare
2
3import (
4 "fmt"
5 "reflect"
6)
7
8// Any type which is a union member must implement this interface. You must
9// also call RegisterUnion for go-bare to marshal or unmarshal messages which
10// utilize your union type.
11type Union interface {
12 IsUnion()
13}
14
15type UnionTags struct {
16 iface reflect.Type
17 tags map[reflect.Type]uint64
18 types map[uint64]reflect.Type
19}
20
21var unionInterface = reflect.TypeOf((*Union)(nil)).Elem()
22var unionRegistry map[reflect.Type]*UnionTags
23
24func init() {
25 unionRegistry = make(map[reflect.Type]*UnionTags)
26}
27
28// Registers a union type in this context. Pass the union interface and the
29// list of types associated with it, sorted ascending by their union tag.
30func RegisterUnion(iface interface{}) *UnionTags {
31 ity := reflect.TypeOf(iface).Elem()
32 if _, ok := unionRegistry[ity]; ok {
33 panic(fmt.Errorf("Type %s has already been registered", ity.Name()))
34 }
35
36 if !ity.Implements(reflect.TypeOf((*Union)(nil)).Elem()) {
37 panic(fmt.Errorf("Type %s does not implement bare.Union", ity.Name()))
38 }
39
40 utypes := &UnionTags{
41 iface: ity,
42 tags: make(map[reflect.Type]uint64),
43 types: make(map[uint64]reflect.Type),
44 }
45 unionRegistry[ity] = utypes
46 return utypes
47}
48
49func (ut *UnionTags) Member(t interface{}, tag uint64) *UnionTags {
50 ty := reflect.TypeOf(t)
51 if !ty.AssignableTo(ut.iface) {
52 panic(fmt.Errorf("Type %s does not implement interface %s",
53 ty.Name(), ut.iface.Name()))
54 }
55 if _, ok := ut.tags[ty]; ok {
56 panic(fmt.Errorf("Type %s is already registered for union %s",
57 ty.Name(), ut.iface.Name()))
58 }
59 if _, ok := ut.types[tag]; ok {
60 panic(fmt.Errorf("Tag %d is already registered for union %s",
61 tag, ut.iface.Name()))
62 }
63 ut.tags[ty] = tag
64 ut.types[tag] = ty
65 return ut
66}
67
68func (ut *UnionTags) TagFor(v interface{}) (uint64, bool) {
69 tag, ok := ut.tags[reflect.TypeOf(v)]
70 return tag, ok
71}
72
73func (ut *UnionTags) TypeFor(tag uint64) (reflect.Type, bool) {
74 t, ok := ut.types[tag]
75 return t, ok
76}
Note: See TracBrowser for help on using the repository browser.