From 94d27fa0e3b3679ab53aa41a71e250e872ea99f7 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Tue, 10 Mar 2026 09:01:35 -0500 Subject: [PATCH] Implement Iterator interfaces for LoadedValueIterator This commit implements: - ArrayIterator interface for ArrayLoadedValueIterator - MapIterator interface for MapLoadedValueIterator --- array_iterator.go | 7 +++++ array_test.go | 26 +++++++++++++++++- map_iterator.go | 21 +++++++++++++++ map_test.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 120 insertions(+), 2 deletions(-) diff --git a/array_iterator.go b/array_iterator.go index 0424cefe..d07f25be 100644 --- a/array_iterator.go +++ b/array_iterator.go @@ -228,6 +228,8 @@ type ArrayLoadedValueIterator struct { dataIterator *arrayLoadedElementIterator } +var _ ArrayIterator = &ArrayLoadedValueIterator{} + func (i *ArrayLoadedValueIterator) nextDataIterator() (*arrayLoadedElementIterator, error) { // Iterate parents (LIFO) to find next loaded array data slab. @@ -268,6 +270,11 @@ func (i *ArrayLoadedValueIterator) nextDataIterator() (*arrayLoadedElementIterat return nil, nil } +// CanMutate returns false. +func (i *ArrayLoadedValueIterator) CanMutate() bool { + return false +} + // Next iterates and returns next loaded element. // It returns nil Value at end of loaded elements. func (i *ArrayLoadedValueIterator) Next() (Value, error) { diff --git a/array_test.go b/array_test.go index 2e908b3b..cf444b2b 100644 --- a/array_test.go +++ b/array_test.go @@ -6326,8 +6326,32 @@ func createArrayWithSimpleAndChildArrayValues( } func testArrayLoadedElements(t *testing.T, array *atree.Array, expectedValues testutils.ExpectedArrayValue) { + // Test Next + + iter, err := array.ReadOnlyLoadedValueIterator() + require.NoError(t, err) + require.False(t, iter.CanMutate()) + i := 0 - err := array.IterateReadOnlyLoadedValues(func(v atree.Value) (bool, error) { + for { + v, err := iter.Next() + require.NoError(t, err) + + if v == nil { + break + } + + require.True(t, i < len(expectedValues)) + testValueEqual(t, expectedValues[i], v) + + i++ + } + require.Equal(t, len(expectedValues), i) + + // Test callback + + i = 0 + err = array.IterateReadOnlyLoadedValues(func(v atree.Value) (bool, error) { require.True(t, i < len(expectedValues)) testValueEqual(t, expectedValues[i], v) i++ diff --git a/map_iterator.go b/map_iterator.go index 21fe6200..5b2b9847 100644 --- a/map_iterator.go +++ b/map_iterator.go @@ -506,6 +506,8 @@ type MapLoadedValueIterator struct { dataIterator *mapLoadedElementIterator } +var _ MapIterator = &MapLoadedValueIterator{} + func (i *MapLoadedValueIterator) nextDataIterator() (*mapLoadedElementIterator, error) { // Iterate parents (LIFO) to find next loaded map data slab. @@ -546,6 +548,25 @@ func (i *MapLoadedValueIterator) nextDataIterator() (*mapLoadedElementIterator, return nil, nil } +// CanMutate returns false. +func (i *MapLoadedValueIterator) CanMutate() bool { + return false +} + +// NextKey iterates and returns next loaded key. +// It returns nil key at end of loaded elements. +func (i *MapLoadedValueIterator) NextKey() (Value, error) { + key, _, err := i.Next() + return key, err +} + +// NextValue iterates and returns next loaded value. +// It returns nil Value at end of loaded elements. +func (i *MapLoadedValueIterator) NextValue() (Value, error) { + _, value, err := i.Next() + return value, err +} + // Next iterates and returns next loaded element. // It returns nil Value at end of loaded elements. func (i *MapLoadedValueIterator) Next() (Value, Value, error) { diff --git a/map_test.go b/map_test.go index d19385aa..6878e4fc 100644 --- a/map_test.go +++ b/map_test.go @@ -16668,8 +16668,74 @@ func createMapWithSimpleAndChildArrayValues( } func testMapLoadedElements(t *testing.T, m *atree.OrderedMap, expectedValues [][2]atree.Value) { + // Test NextKey + iter, err := m.ReadOnlyLoadedValueIterator() + require.NoError(t, err) + require.False(t, iter.CanMutate()) + i := 0 - err := m.IterateReadOnlyLoadedValues(func(k atree.Value, v atree.Value) (bool, error) { + for { + k, err := iter.NextKey() + require.NoError(t, err) + + if k == nil { + break + } + + require.True(t, i < len(expectedValues)) + testValueEqual(t, expectedValues[i][0], k) + + i++ + } + require.Equal(t, len(expectedValues), i) + + // Test NextValue + + iter, err = m.ReadOnlyLoadedValueIterator() + require.NoError(t, err) + + i = 0 + for { + v, err := iter.NextValue() + require.NoError(t, err) + + if v == nil { + break + } + + require.True(t, i < len(expectedValues)) + testValueEqual(t, expectedValues[i][1], v) + + i++ + } + require.Equal(t, len(expectedValues), i) + + // Test Next + + iter, err = m.ReadOnlyLoadedValueIterator() + require.NoError(t, err) + + i = 0 + for { + k, v, err := iter.Next() + require.NoError(t, err) + + if v == nil { + break + } + + require.True(t, i < len(expectedValues)) + testValueEqual(t, expectedValues[i][0], k) + testValueEqual(t, expectedValues[i][1], v) + + i++ + } + require.Equal(t, len(expectedValues), i) + + // Test callback + + i = 0 + err = m.IterateReadOnlyLoadedValues(func(k atree.Value, v atree.Value) (bool, error) { require.True(t, i < len(expectedValues)) testValueEqual(t, expectedValues[i][0], k) testValueEqual(t, expectedValues[i][1], v)