diff --git a/go/types/map.go b/go/types/map.go index 7d387fb1fd..4610250b82 100644 --- a/go/types/map.go +++ b/go/types/map.go @@ -5,6 +5,7 @@ package types import ( + "fmt" "sort" "github.com/attic-labs/noms/go/d" @@ -140,6 +141,16 @@ func (m Map) Last() (Value, Value) { return m.firstOrLast(true) } +func (m Map) At(idx uint64) (key, value Value) { + if idx >= m.Len() { + panic(fmt.Errorf("Out of bounds: %s >= %s", idx, m.Len())) + } + + cur := newCursorAtIndex(m.seq, idx) + entry := cur.current().(mapEntry) + return entry.key, entry.value +} + func (m Map) MaybeGet(key Value) (v Value, ok bool) { cur := newCursorAtValue(m.seq, key, false, false) if !cur.valid() { diff --git a/go/types/map_test.go b/go/types/map_test.go index d018126b31..7773756dfc 100644 --- a/go/types/map_test.go +++ b/go/types/map_test.go @@ -1254,3 +1254,20 @@ func TestMapIterFrom(t *testing.T) { assert.True(kvs[0:0].Equals(test(m1, Number(100), Number(1000)))) assert.True(kvs[50:60].Equals(test(m1, Number(0), Number(8)))) } + +func TestMapAt(t *testing.T) { + assert := assert.New(t) + + values := []Value{Bool(false), Number(42), String('a'), String('b'), String('c'), String('d')} + m := NewMap(values...) + + for i := 0; i < len(values); i += 2 { + k, v := m.At(uint64(i / 2)) + assert.Equal(values[i], k) + assert.Equal(values[i+1], v) + } + + assert.Panics(func() { + m.At(42) + }) +} diff --git a/go/types/set.go b/go/types/set.go index 9652cede64..24bf86133a 100644 --- a/go/types/set.go +++ b/go/types/set.go @@ -5,6 +5,7 @@ package types import ( + "fmt" "sort" "github.com/attic-labs/noms/go/hash" @@ -114,6 +115,15 @@ func (s Set) First() Value { return cur.current().(Value) } +func (s Set) At(idx uint64) Value { + if idx >= s.Len() { + panic(fmt.Errorf("Out of bounds: %s >= %s", idx, s.Len())) + } + + cur := newCursorAtIndex(s.seq, idx) + return cur.current().(Value) +} + func (s Set) Insert(values ...Value) Set { if len(values) == 0 { return s diff --git a/go/types/set_test.go b/go/types/set_test.go index 16bc65d3b6..2a43d3ea27 100644 --- a/go/types/set_test.go +++ b/go/types/set_test.go @@ -986,3 +986,18 @@ func TestSetRemoveLastWhenNotLoaded(t *testing.T) { assert.True(ts.toSet().Equals(ns)) } } + +func TestSetAt(t *testing.T) { + assert := assert.New(t) + + values := []Value{Bool(false), Number(42), String('a'), String('b'), String('c')} + s := NewSet(values...) + + for i, v := range values { + assert.Equal(v, s.At(uint64(i))) + } + + assert.Panics(func() { + s.At(42) + }) +}