entry.gno

2.74 Kb ยท 149 lines
  1package collection
  2
  3import "gno.land/p/demo/ufmt"
  4
  5// Entry represents a single object in the collection with its ID
  6type Entry struct {
  7	ID  string
  8	Obj any
  9}
 10
 11// String returns a string representation of the Entry
 12func (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}
 18
 19// EntryIterator provides iteration over collection entries
 20type EntryIterator struct {
 21	collection *Collection
 22	indexName  string
 23	key        string
 24	currentID  string
 25	currentObj any
 26	err        error
 27	closed     bool
 28
 29	// For multi-value cases
 30	ids        []string
 31	currentIdx int
 32}
 33
 34func (ei *EntryIterator) Close() error {
 35	ei.closed = true
 36	ei.currentID = ""
 37	ei.currentObj = nil
 38	ei.ids = nil
 39	return nil
 40}
 41
 42func (ei *EntryIterator) Next() bool {
 43	if ei == nil || ei.closed || ei.err != nil {
 44		return false
 45	}
 46
 47	// Handle ID index specially
 48	if ei.indexName == IDIndex {
 49		if ei.currentID != "" { // We've already returned the single value
 50			return false
 51		}
 52		obj, exists := ei.collection.indexes[IDIndex].tree.Get(ei.key)
 53		if !exists {
 54			return false
 55		}
 56		ei.currentID = ei.key
 57		ei.currentObj = obj
 58		return true
 59	}
 60
 61	// Get the index
 62	idx, exists := ei.collection.indexes[ei.indexName]
 63	if !exists {
 64		return false
 65	}
 66
 67	// Initialize ids slice if needed
 68	if ei.ids == nil {
 69		idData, exists := idx.tree.Get(ei.key)
 70		if !exists {
 71			return false
 72		}
 73
 74		switch stored := idData.(type) {
 75		case []string:
 76			ei.ids = stored
 77			ei.currentIdx = -1
 78		case string:
 79			ei.ids = []string{stored}
 80			ei.currentIdx = -1
 81		default:
 82			return false
 83		}
 84	}
 85
 86	// Move to next ID
 87	ei.currentIdx++
 88	if ei.currentIdx >= len(ei.ids) {
 89		return false
 90	}
 91
 92	// Fetch the actual object
 93	ei.currentID = ei.ids[ei.currentIdx]
 94	obj, exists := ei.collection.indexes[IDIndex].tree.Get(ei.currentID)
 95	if !exists {
 96		// Skip invalid entries
 97		return ei.Next()
 98	}
 99	ei.currentObj = obj
100	return true
101}
102
103func (ei *EntryIterator) Error() error {
104	return ei.err
105}
106
107func (ei *EntryIterator) Value() *Entry {
108	if ei == nil || ei.closed || ei.currentID == "" {
109		return nil
110	}
111	return &Entry{
112		ID:  ei.currentID,
113		Obj: ei.currentObj,
114	}
115}
116
117func (ei *EntryIterator) Empty() bool {
118	if ei == nil || ei.closed || ei.err != nil {
119		return true
120	}
121
122	// Handle ID index specially
123	if ei.indexName == IDIndex {
124		_, exists := ei.collection.indexes[IDIndex].tree.Get(ei.key)
125		return !exists
126	}
127
128	// Get the index
129	idx, exists := ei.collection.indexes[ei.indexName]
130	if !exists {
131		return true
132	}
133
134	// Check if key exists in index
135	idData, exists := idx.tree.Get(ei.key)
136	if !exists {
137		return true
138	}
139
140	// Check if there are any valid IDs
141	switch stored := idData.(type) {
142	case []string:
143		return len(stored) == 0
144	case string:
145		return stored == ""
146	default:
147		return true
148	}
149}