From 66fd0881c7960cd3499b44c2b59aaf1378bc4229 Mon Sep 17 00:00:00 2001 From: Erik Arvidsson Date: Thu, 29 Oct 2015 18:13:44 -0400 Subject: [PATCH] Make Map TypeRef per instance This is so that we can use type.Map for "unknown" map types when decoding chunks. --- types/map.go | 89 ++++++++++++++++++++++++----------------------- types/map_test.go | 18 ++++++++++ 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/types/map.go b/types/map.go index 8131aa1004..d4ee8a2530 100644 --- a/types/map.go +++ b/types/map.go @@ -9,48 +9,49 @@ import ( type Map struct { data mapData // sorted by entry.key.Ref() + t TypeRef ref *ref.Ref } type mapData []mapEntry func NewMap(kv ...Value) Map { - return newMapFromData(buildMapData(mapData{}, kv)) + return newMapFromData(buildMapData(mapData{}, kv), mapTypeRef) } -func (fm Map) First() (Value, Value) { - if len(fm.data) == 0 { +func (m Map) First() (Value, Value) { + if len(m.data) == 0 { return nil, nil } else { - entry := fm.data[0] + entry := m.data[0] return entry.key, entry.value } } -func (fm Map) Len() uint64 { - return uint64(len(fm.data)) +func (m Map) Len() uint64 { + return uint64(len(m.data)) } -func (fm Map) Empty() bool { - return fm.Len() == uint64(0) +func (m Map) Empty() bool { + return m.Len() == uint64(0) } -func (fm Map) Has(key Value) bool { - idx := indexMapData(fm.data, key.Ref()) - return idx < len(fm.data) && fm.data[idx].key.Equals(key) +func (m Map) Has(key Value) bool { + idx := indexMapData(m.data, key.Ref()) + return idx < len(m.data) && m.data[idx].key.Equals(key) } -func (fm Map) Get(key Value) Value { - if v, ok := fm.MaybeGet(key); ok { +func (m Map) Get(key Value) Value { + if v, ok := m.MaybeGet(key); ok { return v } return nil } -func (fm Map) MaybeGet(key Value) (v Value, ok bool) { - idx := indexMapData(fm.data, key.Ref()) - if idx < len(fm.data) { - entry := fm.data[idx] +func (m Map) MaybeGet(key Value) (v Value, ok bool) { + idx := indexMapData(m.data, key.Ref()) + if idx < len(m.data) { + entry := m.data[idx] if entry.key.Equals(key) { return entry.value, true } @@ -58,30 +59,30 @@ func (fm Map) MaybeGet(key Value) (v Value, ok bool) { return } -func (fm Map) Set(key Value, val Value) Map { - return newMapFromData(buildMapData(fm.data, []Value{key, val})) +func (m Map) Set(key Value, val Value) Map { + return newMapFromData(buildMapData(m.data, []Value{key, val}), m.t) } -func (fm Map) SetM(kv ...Value) Map { - return newMapFromData(buildMapData(fm.data, kv)) +func (m Map) SetM(kv ...Value) Map { + return newMapFromData(buildMapData(m.data, kv), m.t) } -func (fm Map) Remove(k Value) Map { - idx := indexMapData(fm.data, k.Ref()) - if idx == len(fm.data) || !fm.data[idx].key.Equals(k) { - return fm +func (m Map) Remove(k Value) Map { + idx := indexMapData(m.data, k.Ref()) + if idx == len(m.data) || !m.data[idx].key.Equals(k) { + return m } - m := make(mapData, len(fm.data)-1) - copy(m, fm.data[:idx]) - copy(m[idx:], fm.data[idx+1:]) - return newMapFromData(m) + data := make(mapData, len(m.data)-1) + copy(data, m.data[:idx]) + copy(data[idx:], m.data[idx+1:]) + return newMapFromData(data, m.t) } type mapIterCallback func(key, value Value) (stop bool) -func (fm Map) Iter(cb mapIterCallback) { - for _, entry := range fm.data { +func (m Map) Iter(cb mapIterCallback) { + for _, entry := range m.data { if cb(entry.key, entry.value) { break } @@ -90,27 +91,27 @@ func (fm Map) Iter(cb mapIterCallback) { type mapIterAllCallback func(key, value Value) -func (fm Map) IterAll(cb mapIterAllCallback) { - for _, entry := range fm.data { +func (m Map) IterAll(cb mapIterAllCallback) { + for _, entry := range m.data { cb(entry.key, entry.value) } } type mapFilterCallback func(key, value Value) (keep bool) -func (fm Map) Filter(cb mapFilterCallback) Map { +func (m Map) Filter(cb mapFilterCallback) Map { data := mapData{} - for _, entry := range fm.data { + for _, entry := range m.data { if cb(entry.key, entry.value) { data = append(data, entry) } } // Already sorted. - return newMapFromData(data) + return newMapFromData(data, m.t) } -func (fm Map) Ref() ref.Ref { - return EnsureRef(fm.ref, fm) +func (m Map) Ref() ref.Ref { + return EnsureRef(m.ref, m) } func (m Map) Equals(other Value) (res bool) { @@ -120,8 +121,8 @@ func (m Map) Equals(other Value) (res bool) { return false } -func (fm Map) Chunks() (futures []Future) { - for _, entry := range fm.data { +func (m Map) Chunks() (futures []Future) { + for _, entry := range m.data { futures = appendValueToChunks(futures, entry.key) futures = appendValueToChunks(futures, entry.value) } @@ -130,8 +131,8 @@ func (fm Map) Chunks() (futures []Future) { var mapTypeRef = MakeCompoundTypeRef(MapKind, MakePrimitiveTypeRef(ValueKind), MakePrimitiveTypeRef(ValueKind)) -func (fm Map) TypeRef() TypeRef { - return mapTypeRef +func (m Map) TypeRef() TypeRef { + return m.t } func init() { @@ -145,8 +146,8 @@ type mapEntry struct { value Value } -func newMapFromData(data mapData) Map { - return Map{data, &ref.Ref{}} +func newMapFromData(data mapData, t TypeRef) Map { + return Map{data, t, &ref.Ref{}} } func buildMapData(oldData mapData, values []Value) mapData { diff --git a/types/map_test.go b/types/map_test.go index 15f520718c..766ac6ada7 100644 --- a/types/map_test.go +++ b/types/map_test.go @@ -219,6 +219,24 @@ func TestMapTypeRef(t *testing.T) { assert := assert.New(t) m := NewMap() assert.True(m.TypeRef().Equals(MakeCompoundTypeRef(MapKind, MakePrimitiveTypeRef(ValueKind), MakePrimitiveTypeRef(ValueKind)))) + + tr := MakeCompoundTypeRef(MapKind, MakePrimitiveTypeRef(StringKind), MakePrimitiveTypeRef(Int64Kind)) + m = newMapFromData(mapData{}, tr) + assert.Equal(tr, m.TypeRef()) + + m = m.Set(NewString("A"), UInt64(1)) + assert.Equal(tr, m.TypeRef()) + + m = m.SetM(NewString("B"), UInt64(2), NewString("C"), UInt64(2)) + assert.Equal(tr, m.TypeRef()) + + m = m.Remove(NewString("B")) + assert.Equal(tr, m.TypeRef()) + + m = m.Filter(func(k, v Value) bool { + return true + }) + assert.Equal(tr, m.TypeRef()) } func TestMapChunks(t *testing.T) {