1package collection23import "gno.land/p/nt/ufmt/v0"45// Entry represents a single object in the collection with its ID6type Entry struct {7 ID string8 Obj any9}1011// String returns a string representation of the Entry12func (e *Entry) String() string {13 if e == nil {14 return "<nil>"15 }16 return ufmt.Sprintf("Entry{ID: %s, Obj: %v}", e.ID, e.Obj)17}1819// EntryIterator provides iteration over collection entries20type EntryIterator struct {21 collection *Collection22 indexName string23 key string24 currentID string25 currentObj any26 err error27 closed bool2829 // For multi-value cases30 ids []string31 currentIdx int32}3334func (ei *EntryIterator) Close() error {35 ei.closed = true36 ei.currentID = ""37 ei.currentObj = nil38 ei.ids = nil39 return nil40}4142func (ei *EntryIterator) Next() bool {43 if ei == nil || ei.closed || ei.err != nil {44 return false45 }4647 // Handle ID index specially48 if ei.indexName == IDIndex {49 if ei.currentID != "" { // We've already returned the single value50 return false51 }52 obj := ei.collection.indexes[IDIndex].tree.Get(ei.key)53 if obj == nil {54 return false55 }56 ei.currentID = ei.key57 ei.currentObj = obj58 return true59 }6061 // Get the index62 idx, exists := ei.collection.indexes[ei.indexName]63 if !exists {64 return false65 }6667 // Initialize ids slice if needed68 if ei.ids == nil {69 idData := idx.tree.Get(ei.key)70 if idData == nil {71 return false72 }7374 switch stored := idData.(type) {75 case []string:76 ei.ids = stored77 ei.currentIdx = -178 case string:79 ei.ids = []string{stored}80 ei.currentIdx = -181 default:82 return false83 }84 }8586 // Move to next ID87 ei.currentIdx++88 if ei.currentIdx >= len(ei.ids) {89 return false90 }9192 // Fetch the actual object93 ei.currentID = ei.ids[ei.currentIdx]94 obj := ei.collection.indexes[IDIndex].tree.Get(ei.currentID)95 if obj == nil {96 // Skip invalid entries97 return ei.Next()98 }99 ei.currentObj = obj100 return true101}102103func (ei *EntryIterator) Error() error {104 return ei.err105}106107func (ei *EntryIterator) Value() *Entry {108 if ei == nil || ei.closed || ei.currentID == "" {109 return nil110 }111 return &Entry{112 ID: ei.currentID,113 Obj: ei.currentObj,114 }115}116117func (ei *EntryIterator) Empty() bool {118 if ei == nil || ei.closed || ei.err != nil {119 return true120 }121122 // Handle ID index specially123 if ei.indexName == IDIndex {124 return !ei.collection.indexes[IDIndex].tree.Has(ei.key)125 }126127 // Get the index128 idx, exists := ei.collection.indexes[ei.indexName]129 if !exists {130 return true131 }132133 // Check if key exists in index134 idData := idx.tree.Get(ei.key)135 if idData == nil {136 return true137 }138139 // Check if there are any valid IDs140 switch stored := idData.(type) {141 case []string:142 return len(stored) == 0143 case string:144 return stored == ""145 default:146 return true147 }148}149Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.