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}