github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/store/prefix/store.go (about) 1 package prefix 2 3 import ( 4 "bytes" 5 6 "github.com/gnolang/gno/tm2/pkg/store/cache" 7 "github.com/gnolang/gno/tm2/pkg/store/types" 8 ) 9 10 var _ types.Store = Store{} 11 12 // Store is similar with tendermint/tendermint/libs/db/prefix_db 13 // both gives access only to the limited subset of the store 14 // for convenience or safety 15 type Store struct { 16 parent types.Store 17 prefix []byte 18 } 19 20 func New(parent types.Store, prefix []byte) Store { 21 return Store{ 22 parent: parent, 23 prefix: prefix, 24 } 25 } 26 27 func cloneAppend(bz []byte, tail []byte) (res []byte) { 28 res = make([]byte, len(bz)+len(tail)) 29 copy(res, bz) 30 copy(res[len(bz):], tail) 31 return 32 } 33 34 func (s Store) key(key []byte) (res []byte) { 35 if key == nil { 36 panic("nil key on Store") 37 } 38 res = cloneAppend(s.prefix, key) 39 return 40 } 41 42 // Implements Store 43 func (s Store) CacheWrap() types.Store { 44 return cache.New(s) 45 } 46 47 // Implements Store 48 func (s Store) Write() { 49 panic("unexpected .Write() on prefix.Store") 50 } 51 52 // Implements Store 53 func (s Store) Get(key []byte) []byte { 54 res := s.parent.Get(s.key(key)) 55 return res 56 } 57 58 // Implements Store 59 func (s Store) Has(key []byte) bool { 60 return s.parent.Has(s.key(key)) 61 } 62 63 // Implements Store 64 func (s Store) Set(key, value []byte) { 65 types.AssertValidKey(key) 66 types.AssertValidValue(value) 67 s.parent.Set(s.key(key), value) 68 } 69 70 // Implements Store 71 func (s Store) Delete(key []byte) { 72 s.parent.Delete(s.key(key)) 73 } 74 75 // Implements Store 76 // Check https://github.com/tendermint/classic/blob/master/libs/db/prefix_db.go#L106 77 func (s Store) Iterator(start, end []byte) types.Iterator { 78 newstart := cloneAppend(s.prefix, start) 79 80 var newend []byte 81 if end == nil { 82 newend = cpIncr(s.prefix) 83 } else { 84 newend = cloneAppend(s.prefix, end) 85 } 86 87 iter := s.parent.Iterator(newstart, newend) 88 89 return newPrefixIterator(s.prefix, start, end, iter) 90 } 91 92 // Implements Store 93 // Check https://github.com/tendermint/classic/blob/master/libs/db/prefix_db.go#L129 94 func (s Store) ReverseIterator(start, end []byte) types.Iterator { 95 newstart := cloneAppend(s.prefix, start) 96 97 var newend []byte 98 if end == nil { 99 newend = cpIncr(s.prefix) 100 } else { 101 newend = cloneAppend(s.prefix, end) 102 } 103 104 iter := s.parent.ReverseIterator(newstart, newend) 105 106 return newPrefixIterator(s.prefix, start, end, iter) 107 } 108 109 var _ types.Iterator = (*prefixIterator)(nil) 110 111 type prefixIterator struct { 112 prefix []byte 113 start, end []byte 114 iter types.Iterator 115 valid bool 116 } 117 118 func newPrefixIterator(prefix, start, end []byte, parent types.Iterator) *prefixIterator { 119 return &prefixIterator{ 120 prefix: prefix, 121 start: start, 122 end: end, 123 iter: parent, 124 valid: parent.Valid() && bytes.HasPrefix(parent.Key(), prefix), 125 } 126 } 127 128 // Implements Iterator 129 func (iter *prefixIterator) Domain() ([]byte, []byte) { 130 return iter.start, iter.end 131 } 132 133 // Implements Iterator 134 func (iter *prefixIterator) Valid() bool { 135 return iter.valid && iter.iter.Valid() 136 } 137 138 // Implements Iterator 139 func (iter *prefixIterator) Next() { 140 if !iter.valid { 141 panic("prefixIterator invalid, cannot call Next()") 142 } 143 iter.iter.Next() 144 if !iter.iter.Valid() || !bytes.HasPrefix(iter.iter.Key(), iter.prefix) { 145 iter.valid = false 146 } 147 } 148 149 // Implements Iterator 150 func (iter *prefixIterator) Key() (key []byte) { 151 if !iter.valid { 152 panic("prefixIterator invalid, cannot call Key()") 153 } 154 key = iter.iter.Key() 155 key = stripPrefix(key, iter.prefix) 156 return 157 } 158 159 // Implements Iterator 160 func (iter *prefixIterator) Value() []byte { 161 if !iter.valid { 162 panic("prefixIterator invalid, cannot call Value()") 163 } 164 return iter.iter.Value() 165 } 166 167 // Implements Iterator 168 func (iter *prefixIterator) Close() { 169 iter.iter.Close() 170 } 171 172 // copied from github.com/tendermint/classic/libs/db/prefix_db.go 173 func stripPrefix(key []byte, prefix []byte) []byte { 174 if len(key) < len(prefix) || !bytes.Equal(key[:len(prefix)], prefix) { 175 panic("should not happen") 176 } 177 return key[len(prefix):] 178 } 179 180 // wrapping types.PrefixEndBytes 181 func cpIncr(bz []byte) []byte { 182 return types.PrefixEndBytes(bz) 183 }