diff --git a/nomdl/codegen/enum.tmpl b/nomdl/codegen/enum.tmpl index e86f247d2b..42f84902ff 100644 --- a/nomdl/codegen/enum.tmpl +++ b/nomdl/codegen/enum.tmpl @@ -21,13 +21,15 @@ func (e {{.Name}}) TypeRef() {{$typesPackage}}TypeRef { func init() { __typeRefFor{{.Name}} = {{$typesPackage}}MakeTypeRef(__{{.PackageName}}PackageInFile_{{.FileID}}_CachedRef, {{.Ordinal}}) - {{$typesPackage}}RegisterFromValFunction(__typeRefFor{{.Name}}, func(v {{$typesPackage}}Value) {{$typesPackage}}Value { - return {{.Name}}(uint32(v.({{$typesPackage}}UInt32))) - }) + {{$typesPackage}}RegisterEnum(__typeRefFor{{.Name}}, builderFor{{.Name}}, readerFor{{.Name}}) } -func (e {{.Name}}) InternalImplementation() uint32 { - return uint32(e) +func builderFor{{.Name}}(v uint32) {{$typesPackage}}Value { + return {{.Name}}(v) +} + +func readerFor{{.Name}}(v {{$typesPackage}}Value) uint32 { + return uint32(v.({{.Name}})) } func (e {{.Name}}) Equals(other {{$typesPackage}}Value) bool { diff --git a/nomdl/codegen/test/gen/enum_struct.noms.go b/nomdl/codegen/test/gen/enum_struct.noms.go index 3391dbba1f..a91b0431cc 100644 --- a/nomdl/codegen/test/gen/enum_struct.noms.go +++ b/nomdl/codegen/test/gen/enum_struct.noms.go @@ -47,13 +47,15 @@ func (e Handedness) TypeRef() types.TypeRef { func init() { __typeRefForHandedness = types.MakeTypeRef(__genPackageInFile_enum_struct_CachedRef, 0) - types.RegisterFromValFunction(__typeRefForHandedness, func(v types.Value) types.Value { - return Handedness(uint32(v.(types.UInt32))) - }) + types.RegisterEnum(__typeRefForHandedness, builderForHandedness, readerForHandedness) } -func (e Handedness) InternalImplementation() uint32 { - return uint32(e) +func builderForHandedness(v uint32) types.Value { + return Handedness(v) +} + +func readerForHandedness(v types.Value) uint32 { + return uint32(v.(Handedness)) } func (e Handedness) Equals(other types.Value) bool { diff --git a/nomdl/codegen/test/gen/sha1_1c216c6.go b/nomdl/codegen/test/gen/sha1_1c216c6.go index a409626292..e7db1195ea 100644 --- a/nomdl/codegen/test/gen/sha1_1c216c6.go +++ b/nomdl/codegen/test/gen/sha1_1c216c6.go @@ -150,13 +150,15 @@ func (e E) TypeRef() types.TypeRef { func init() { __typeRefForE = types.MakeTypeRef(__genPackageInFile_sha1_1c216c6_CachedRef, 1) - types.RegisterFromValFunction(__typeRefForE, func(v types.Value) types.Value { - return E(uint32(v.(types.UInt32))) - }) + types.RegisterEnum(__typeRefForE, builderForE, readerForE) } -func (e E) InternalImplementation() uint32 { - return uint32(e) +func builderForE(v uint32) types.Value { + return E(v) +} + +func readerForE(v types.Value) uint32 { + return uint32(v.(E)) } func (e E) Equals(other types.Value) bool { diff --git a/nomdl/codegen/test/gen/struct_with_dup_list.noms.go b/nomdl/codegen/test/gen/struct_with_dup_list.noms.go index 64b3082773..d5049b7d5e 100644 --- a/nomdl/codegen/test/gen/struct_with_dup_list.noms.go +++ b/nomdl/codegen/test/gen/struct_with_dup_list.noms.go @@ -109,3 +109,136 @@ func (s StructWithDupList) SetL(val ListOfUInt8) StructWithDupList { s.ref = &ref.Ref{} return s } + +// ListOfUInt8 + +type ListOfUInt8 struct { + l types.List + ref *ref.Ref +} + +func NewListOfUInt8() ListOfUInt8 { + return ListOfUInt8{types.NewList(), &ref.Ref{}} +} + +type ListOfUInt8Def []uint8 + +func (def ListOfUInt8Def) New() ListOfUInt8 { + l := make([]types.Value, len(def)) + for i, d := range def { + l[i] = types.UInt8(d) + } + return ListOfUInt8{types.NewList(l...), &ref.Ref{}} +} + +func (l ListOfUInt8) Def() ListOfUInt8Def { + d := make([]uint8, l.Len()) + for i := uint64(0); i < l.Len(); i++ { + d[i] = uint8(l.l.Get(i).(types.UInt8)) + } + return d +} + +func (l ListOfUInt8) InternalImplementation() types.List { + return l.l +} + +func (l ListOfUInt8) Equals(other types.Value) bool { + return other != nil && __typeRefForListOfUInt8.Equals(other.TypeRef()) && l.Ref() == other.Ref() +} + +func (l ListOfUInt8) Ref() ref.Ref { + return types.EnsureRef(l.ref, l) +} + +func (l ListOfUInt8) Chunks() (chunks []ref.Ref) { + chunks = append(chunks, l.TypeRef().Chunks()...) + chunks = append(chunks, l.l.Chunks()...) + return +} + +// A Noms Value that describes ListOfUInt8. +var __typeRefForListOfUInt8 types.TypeRef + +func (m ListOfUInt8) TypeRef() types.TypeRef { + return __typeRefForListOfUInt8 +} + +func init() { + __typeRefForListOfUInt8 = types.MakeCompoundTypeRef(types.ListKind, types.MakePrimitiveTypeRef(types.UInt8Kind)) + types.RegisterFromValFunction(__typeRefForListOfUInt8, func(v types.Value) types.Value { + return ListOfUInt8{v.(types.List), &ref.Ref{}} + }) +} + +func (l ListOfUInt8) Len() uint64 { + return l.l.Len() +} + +func (l ListOfUInt8) Empty() bool { + return l.Len() == uint64(0) +} + +func (l ListOfUInt8) Get(i uint64) uint8 { + return uint8(l.l.Get(i).(types.UInt8)) +} + +func (l ListOfUInt8) Slice(idx uint64, end uint64) ListOfUInt8 { + return ListOfUInt8{l.l.Slice(idx, end), &ref.Ref{}} +} + +func (l ListOfUInt8) Set(i uint64, val uint8) ListOfUInt8 { + return ListOfUInt8{l.l.Set(i, types.UInt8(val)), &ref.Ref{}} +} + +func (l ListOfUInt8) Append(v ...uint8) ListOfUInt8 { + return ListOfUInt8{l.l.Append(l.fromElemSlice(v)...), &ref.Ref{}} +} + +func (l ListOfUInt8) Insert(idx uint64, v ...uint8) ListOfUInt8 { + return ListOfUInt8{l.l.Insert(idx, l.fromElemSlice(v)...), &ref.Ref{}} +} + +func (l ListOfUInt8) Remove(idx uint64, end uint64) ListOfUInt8 { + return ListOfUInt8{l.l.Remove(idx, end), &ref.Ref{}} +} + +func (l ListOfUInt8) RemoveAt(idx uint64) ListOfUInt8 { + return ListOfUInt8{(l.l.RemoveAt(idx)), &ref.Ref{}} +} + +func (l ListOfUInt8) fromElemSlice(p []uint8) []types.Value { + r := make([]types.Value, len(p)) + for i, v := range p { + r[i] = types.UInt8(v) + } + return r +} + +type ListOfUInt8IterCallback func(v uint8, i uint64) (stop bool) + +func (l ListOfUInt8) Iter(cb ListOfUInt8IterCallback) { + l.l.Iter(func(v types.Value, i uint64) bool { + return cb(uint8(v.(types.UInt8)), i) + }) +} + +type ListOfUInt8IterAllCallback func(v uint8, i uint64) + +func (l ListOfUInt8) IterAll(cb ListOfUInt8IterAllCallback) { + l.l.IterAll(func(v types.Value, i uint64) { + cb(uint8(v.(types.UInt8)), i) + }) +} + +type ListOfUInt8FilterCallback func(v uint8, i uint64) (keep bool) + +func (l ListOfUInt8) Filter(cb ListOfUInt8FilterCallback) ListOfUInt8 { + nl := NewListOfUInt8() + l.IterAll(func(v uint8, i uint64) { + if cb(v, i) { + nl = nl.Append(v) + } + }) + return nl +} diff --git a/nomdl/codegen/test/gen/struct_with_imports.noms.go b/nomdl/codegen/test/gen/struct_with_imports.noms.go index 835433e9c9..eb9ede4efe 100644 --- a/nomdl/codegen/test/gen/struct_with_imports.noms.go +++ b/nomdl/codegen/test/gen/struct_with_imports.noms.go @@ -49,13 +49,15 @@ func (e LocalE) TypeRef() types.TypeRef { func init() { __typeRefForLocalE = types.MakeTypeRef(__genPackageInFile_struct_with_imports_CachedRef, 0) - types.RegisterFromValFunction(__typeRefForLocalE, func(v types.Value) types.Value { - return LocalE(uint32(v.(types.UInt32))) - }) + types.RegisterEnum(__typeRefForLocalE, builderForLocalE, readerForLocalE) } -func (e LocalE) InternalImplementation() uint32 { - return uint32(e) +func builderForLocalE(v uint32) types.Value { + return LocalE(v) +} + +func readerForLocalE(v types.Value) uint32 { + return uint32(v.(LocalE)) } func (e LocalE) Equals(other types.Value) bool { diff --git a/nomdl/codegen/test/gen/struct_with_list.noms.go b/nomdl/codegen/test/gen/struct_with_list.noms.go index 4728cf6fa3..f1a708ddb6 100644 --- a/nomdl/codegen/test/gen/struct_with_list.noms.go +++ b/nomdl/codegen/test/gen/struct_with_list.noms.go @@ -163,136 +163,3 @@ func (s StructWithList) SetI(val int64) StructWithList { s.ref = &ref.Ref{} return s } - -// ListOfUInt8 - -type ListOfUInt8 struct { - l types.List - ref *ref.Ref -} - -func NewListOfUInt8() ListOfUInt8 { - return ListOfUInt8{types.NewList(), &ref.Ref{}} -} - -type ListOfUInt8Def []uint8 - -func (def ListOfUInt8Def) New() ListOfUInt8 { - l := make([]types.Value, len(def)) - for i, d := range def { - l[i] = types.UInt8(d) - } - return ListOfUInt8{types.NewList(l...), &ref.Ref{}} -} - -func (l ListOfUInt8) Def() ListOfUInt8Def { - d := make([]uint8, l.Len()) - for i := uint64(0); i < l.Len(); i++ { - d[i] = uint8(l.l.Get(i).(types.UInt8)) - } - return d -} - -func (l ListOfUInt8) InternalImplementation() types.List { - return l.l -} - -func (l ListOfUInt8) Equals(other types.Value) bool { - return other != nil && __typeRefForListOfUInt8.Equals(other.TypeRef()) && l.Ref() == other.Ref() -} - -func (l ListOfUInt8) Ref() ref.Ref { - return types.EnsureRef(l.ref, l) -} - -func (l ListOfUInt8) Chunks() (chunks []ref.Ref) { - chunks = append(chunks, l.TypeRef().Chunks()...) - chunks = append(chunks, l.l.Chunks()...) - return -} - -// A Noms Value that describes ListOfUInt8. -var __typeRefForListOfUInt8 types.TypeRef - -func (m ListOfUInt8) TypeRef() types.TypeRef { - return __typeRefForListOfUInt8 -} - -func init() { - __typeRefForListOfUInt8 = types.MakeCompoundTypeRef(types.ListKind, types.MakePrimitiveTypeRef(types.UInt8Kind)) - types.RegisterFromValFunction(__typeRefForListOfUInt8, func(v types.Value) types.Value { - return ListOfUInt8{v.(types.List), &ref.Ref{}} - }) -} - -func (l ListOfUInt8) Len() uint64 { - return l.l.Len() -} - -func (l ListOfUInt8) Empty() bool { - return l.Len() == uint64(0) -} - -func (l ListOfUInt8) Get(i uint64) uint8 { - return uint8(l.l.Get(i).(types.UInt8)) -} - -func (l ListOfUInt8) Slice(idx uint64, end uint64) ListOfUInt8 { - return ListOfUInt8{l.l.Slice(idx, end), &ref.Ref{}} -} - -func (l ListOfUInt8) Set(i uint64, val uint8) ListOfUInt8 { - return ListOfUInt8{l.l.Set(i, types.UInt8(val)), &ref.Ref{}} -} - -func (l ListOfUInt8) Append(v ...uint8) ListOfUInt8 { - return ListOfUInt8{l.l.Append(l.fromElemSlice(v)...), &ref.Ref{}} -} - -func (l ListOfUInt8) Insert(idx uint64, v ...uint8) ListOfUInt8 { - return ListOfUInt8{l.l.Insert(idx, l.fromElemSlice(v)...), &ref.Ref{}} -} - -func (l ListOfUInt8) Remove(idx uint64, end uint64) ListOfUInt8 { - return ListOfUInt8{l.l.Remove(idx, end), &ref.Ref{}} -} - -func (l ListOfUInt8) RemoveAt(idx uint64) ListOfUInt8 { - return ListOfUInt8{(l.l.RemoveAt(idx)), &ref.Ref{}} -} - -func (l ListOfUInt8) fromElemSlice(p []uint8) []types.Value { - r := make([]types.Value, len(p)) - for i, v := range p { - r[i] = types.UInt8(v) - } - return r -} - -type ListOfUInt8IterCallback func(v uint8, i uint64) (stop bool) - -func (l ListOfUInt8) Iter(cb ListOfUInt8IterCallback) { - l.l.Iter(func(v types.Value, i uint64) bool { - return cb(uint8(v.(types.UInt8)), i) - }) -} - -type ListOfUInt8IterAllCallback func(v uint8, i uint64) - -func (l ListOfUInt8) IterAll(cb ListOfUInt8IterAllCallback) { - l.l.IterAll(func(v types.Value, i uint64) { - cb(uint8(v.(types.UInt8)), i) - }) -} - -type ListOfUInt8FilterCallback func(v uint8, i uint64) (keep bool) - -func (l ListOfUInt8) Filter(cb ListOfUInt8FilterCallback) ListOfUInt8 { - nl := NewListOfUInt8() - l.IterAll(func(v uint8, i uint64) { - if cb(v, i) { - nl = nl.Append(v) - } - }) - return nl -} diff --git a/nomdl/codegen/testDeps/leafDep/leafDep.noms.go b/nomdl/codegen/testDeps/leafDep/leafDep.noms.go index a79200da01..91f7f907f0 100644 --- a/nomdl/codegen/testDeps/leafDep/leafDep.noms.go +++ b/nomdl/codegen/testDeps/leafDep/leafDep.noms.go @@ -150,13 +150,15 @@ func (e E) TypeRef() types.TypeRef { func init() { __typeRefForE = types.MakeTypeRef(__leafDepPackageInFile_leafDep_CachedRef, 1) - types.RegisterFromValFunction(__typeRefForE, func(v types.Value) types.Value { - return E(uint32(v.(types.UInt32))) - }) + types.RegisterEnum(__typeRefForE, builderForE, readerForE) } -func (e E) InternalImplementation() uint32 { - return uint32(e) +func builderForE(v uint32) types.Value { + return E(v) +} + +func readerForE(v types.Value) uint32 { + return uint32(v.(E)) } func (e E) Equals(other types.Value) bool { diff --git a/types/decode_noms_value.go b/types/decode_noms_value.go index 36173604d9..388a6f7351 100644 --- a/types/decode_noms_value.go +++ b/types/decode_noms_value.go @@ -150,7 +150,7 @@ func (r *jsonArrayReader) readMap(t TypeRef, pkg *Package) Value { func (r *jsonArrayReader) readEnum(t TypeRef, pkg *Package) Value { t = fixupTypeRef(t, pkg) - return ToNomsValueFromTypeRef(t, UInt32(r.read().(float64))) + return enumFromTypeRef(uint32(r.read().(float64)), t) } func (r *jsonArrayReader) readPackage(t TypeRef, pkg *Package) Value { diff --git a/types/decode_noms_value_test.go b/types/decode_noms_value_test.go index 89e718eae9..c4a16504ee 100644 --- a/types/decode_noms_value_test.go +++ b/types/decode_noms_value_test.go @@ -359,38 +359,30 @@ func TestReadEnum(t *testing.T) { assert := assert.New(t) cs := chunks.NewMemoryStore() - tref := MakeEnumTypeRef("E", "a", "b", "c") - pkg := NewPackage([]TypeRef{tref}, []ref.Ref{}) + typeDef := MakeEnumTypeRef("E", "a", "b", "c") + pkg := NewPackage([]TypeRef{typeDef}, []ref.Ref{}) pkgRef := RegisterPackage(&pkg) - enumTr := MakeTypeRef(pkgRef, 0) - RegisterFromValFunction(enumTr, func(v Value) Value { - return testEnum{v.(UInt32), enumTr} - }) a := parseJson(`[%d, "%s", 0, 1]`, UnresolvedKind, pkgRef.String()) r := newJsonArrayReader(a, cs) - v := r.readTopLevelValue().(testEnum) - assert.Equal(uint32(1), uint32(v.UInt32)) + v := r.readTopLevelValue().(Enum) + assert.Equal(uint32(1), v.v) } func TestReadValueEnum(t *testing.T) { assert := assert.New(t) cs := chunks.NewMemoryStore() - tref := MakeEnumTypeRef("E", "a", "b", "c") - pkg := NewPackage([]TypeRef{tref}, []ref.Ref{}) + typeDef := MakeEnumTypeRef("E", "a", "b", "c") + pkg := NewPackage([]TypeRef{typeDef}, []ref.Ref{}) pkgRef := RegisterPackage(&pkg) - enumTr := MakeTypeRef(pkgRef, 0) - RegisterFromValFunction(enumTr, func(v Value) Value { - return testEnum{v.(UInt32), enumTr} - }) a := parseJson(`[%d, %d, "%s", 0, 1]`, ValueKind, UnresolvedKind, pkgRef.String()) r := newJsonArrayReader(a, cs) - v := r.readTopLevelValue().(testEnum) - assert.Equal(uint32(1), uint32(v.UInt32)) + v := r.readTopLevelValue().(Enum) + assert.Equal(uint32(1), v.v) } func TestReadRef(t *testing.T) { @@ -460,14 +452,11 @@ func TestReadStructWithEnum(t *testing.T) { return v }) enumTr := MakeTypeRef(pkgRef, 1) - RegisterFromValFunction(enumTr, func(v Value) Value { - return testEnum{v.(UInt32), enumTr} - }) v := r.readTopLevelValue().(Struct) assert.True(v.Get("x").Equals(Int16(42))) - assert.True(v.Get("e").Equals(UInt32(1))) + assert.True(v.Get("e").Equals(Enum{1, enumTr})) assert.True(v.Get("b").Equals(Bool(true))) } diff --git a/types/encode_noms_value.go b/types/encode_noms_value.go index cce9b1f274..0f6db39c9e 100644 --- a/types/encode_noms_value.go +++ b/types/encode_noms_value.go @@ -126,10 +126,6 @@ func (w *jsonArrayWriter) writeValue(v Value, tr TypeRef, pkg *Package) { } // TODO: This is ugly. BUG 452 -type enumImplementation interface { - InternalImplementation() uint32 -} - type listImplementation interface { InternalImplementation() List } @@ -146,10 +142,6 @@ type setImplementation interface { InternalImplementation() Set } -func getEnumFromEnumKind(v Value) uint32 { - return v.(enumImplementation).InternalImplementation() -} - func getListFromListKind(v Value) List { if v, ok := v.(List); ok { return v @@ -243,7 +235,7 @@ func (w *jsonArrayWriter) writeUnresolvedKindValue(v Value, tr TypeRef, pkg *Pac default: d.Chk.Fail("An Unresolved TypeRef can only reference a StructKind or Enum Kind.", "Actually referenced: %+v", typeDef) case EnumKind: - w.write(getEnumFromEnumKind(v)) + w.writeEnum(v, tr, pkg) case StructKind: w.writeStruct(v, tr, typeDef, pkg) } @@ -282,3 +274,9 @@ func (w *jsonArrayWriter) writeStruct(v Value, typeRef, typeDef TypeRef, pkg *Pa w.writeValue(<-c, desc.Union[unionIndex].T, pkg) } } + +func (w *jsonArrayWriter) writeEnum(v Value, t TypeRef, pkg *Package) { + t = fixupTypeRef(t, pkg) + i := enumPrimitiveValueFromTypeRef(v, t) + w.write(i) +} diff --git a/types/encode_noms_value_test.go b/types/encode_noms_value_test.go index 97b64a3c30..a2f312aa46 100644 --- a/types/encode_noms_value_test.go +++ b/types/encode_noms_value_test.go @@ -282,19 +282,6 @@ func TestWriteStructWithBlob(t *testing.T) { assert.EqualValues([]interface{}{UnresolvedKind, pkgRef.String(), int16(0), "AAE="}, w.toArray()) } -type testEnum struct { - UInt32 - t TypeRef -} - -func (e testEnum) TypeRef() TypeRef { - return e.t -} - -func (e testEnum) InternalImplementation() uint32 { - return uint32(e.UInt32) -} - func TestWriteEnum(t *testing.T) { assert := assert.New(t) cs := chunks.NewMemoryStore() @@ -305,7 +292,7 @@ func TestWriteEnum(t *testing.T) { tref := MakeTypeRef(pkgRef, 0) w := newJsonArrayWriter(cs) - w.writeTopLevelValue(testEnum{UInt32: UInt32(1), t: tref}) + w.writeTopLevelValue(Enum{1, tref}) assert.EqualValues([]interface{}{UnresolvedKind, pkgRef.String(), int16(0), uint32(1)}, w.toArray()) } @@ -318,7 +305,7 @@ func TestWriteListOfEnum(t *testing.T) { pkgRef := RegisterPackage(&pkg) et := MakeTypeRef(pkgRef, 0) tref := MakeCompoundTypeRef(ListKind, et) - v := NewList(testEnum{UInt32(0), et}, testEnum{UInt32(1), et}, testEnum{UInt32(2), et}) + v := NewList(Enum{0, et}, Enum{1, et}, Enum{2, et}) w := newJsonArrayWriter(cs) w.writeTopLevelValue(testList{List: v, t: tref}) diff --git a/types/enum.go b/types/enum.go new file mode 100644 index 0000000000..6dc035df54 --- /dev/null +++ b/types/enum.go @@ -0,0 +1,29 @@ +package types + +import "github.com/attic-labs/noms/ref" + +type Enum struct { + v uint32 + t TypeRef +} + +func newEnum(v uint32, t TypeRef) Enum { + return Enum{v, t} +} + +func (e Enum) Equals(other Value) bool { + return other != nil && e.t.Equals(other.TypeRef()) && e.Ref() == other.Ref() +} + +func (e Enum) Ref() ref.Ref { + throwaway := ref.Ref{} + return EnsureRef(&throwaway, e) +} + +func (e Enum) Chunks() []ref.Ref { + return nil +} + +func (e Enum) TypeRef() TypeRef { + return e.t +} diff --git a/types/enum_test.go b/types/enum_test.go new file mode 100644 index 0000000000..05e030cead --- /dev/null +++ b/types/enum_test.go @@ -0,0 +1,34 @@ +package types + +import ( + "testing" + + "github.com/attic-labs/noms/Godeps/_workspace/src/github.com/stretchr/testify/assert" + "github.com/attic-labs/noms/chunks" + "github.com/attic-labs/noms/ref" +) + +func TestGenericEnumWriteRead(t *testing.T) { + assert := assert.New(t) + cs := chunks.NewMemoryStore() + + typeDefA := MakeEnumTypeRef("EA", "aA", "bA") + typeDefB := MakeEnumTypeRef("EB", "aB", "bB") + pkg := NewPackage([]TypeRef{typeDefA, typeDefB}, []ref.Ref{}) + pkgRef := RegisterPackage(&pkg) + typeRefA := MakeTypeRef(pkgRef, 0) + typeRefB := MakeTypeRef(pkgRef, 1) + + vA := Enum{1, typeRefA} + vB := Enum{1, typeRefB} + + assert.False(vA.Equals(vB)) + + rA := WriteValue(vA, cs) + vA2 := ReadValue(rA, cs) + + assert.True(vA.Equals(vA2)) + assert.True(vA2.Equals(vA)) + assert.False(vB.Equals(vA2)) + assert.False(vA2.Equals(vB)) +} diff --git a/types/package_registry.go b/types/package_registry.go index 3129d0ee77..48a8f481b5 100644 --- a/types/package_registry.go +++ b/types/package_registry.go @@ -8,6 +8,8 @@ import ( type structBuilderFunc func() chan Value type structReaderFunc func(v Value) chan Value +type enumBuilderFunc func(v uint32) Value +type enumReaderFunc func(v Value) uint32 type toNomsValueFunc func(v Value) Value type structFuncs struct { @@ -15,10 +17,16 @@ type structFuncs struct { reader structReaderFunc } +type enumFuncs struct { + builder enumBuilderFunc + reader enumReaderFunc +} + var ( packages map[ref.Ref]*Package = map[ref.Ref]*Package{} toNomsValueMap map[ref.Ref]toNomsValueFunc = map[ref.Ref]toNomsValueFunc{} structFuncMap map[ref.Ref]structFuncs = map[ref.Ref]structFuncs{} + enumFuncMap map[ref.Ref]enumFuncs = map[ref.Ref]enumFuncs{} ) // LookupPackage looks for a Package by ref.Ref in the global cache of Noms type packages. @@ -68,3 +76,21 @@ func structReaderForTypeRef(v Value, typeRef, typeDef TypeRef) chan Value { } return structReader(v.(Struct), typeRef, typeDef) } + +func RegisterEnum(t TypeRef, bf enumBuilderFunc, rf enumReaderFunc) { + enumFuncMap[t.Ref()] = enumFuncs{bf, rf} +} + +func enumFromTypeRef(v uint32, t TypeRef) Value { + if s, ok := enumFuncMap[t.Ref()]; ok { + return s.builder(v) + } + return newEnum(v, t) +} + +func enumPrimitiveValueFromTypeRef(v Value, t TypeRef) uint32 { + if s, ok := enumFuncMap[t.Ref()]; ok { + return s.reader(v) + } + return v.(Enum).v +}