github.com/Finschia/finschia-sdk@v0.48.1/store/prefix/store.go (about) 1 package prefix 2 3 import ( 4 "bytes" 5 "errors" 6 "io" 7 8 "github.com/Finschia/finschia-sdk/store/cachekv" 9 "github.com/Finschia/finschia-sdk/store/listenkv" 10 "github.com/Finschia/finschia-sdk/store/tracekv" 11 "github.com/Finschia/finschia-sdk/store/types" 12 ) 13 14 var _ types.KVStore = Store{} 15 16 // Store is similar with tendermint/tendermint/libs/db/prefix_db 17 // both gives access only to the limited subset of the store 18 // for convinience or safety 19 type Store struct { 20 parent types.KVStore 21 prefix []byte 22 } 23 24 func NewStore(parent types.KVStore, prefix []byte) Store { 25 return Store{ 26 parent: parent, 27 prefix: prefix, 28 } 29 } 30 31 func cloneAppend(bz []byte, tail []byte) (res []byte) { 32 res = make([]byte, len(bz)+len(tail)) 33 copy(res, bz) 34 copy(res[len(bz):], tail) 35 return 36 } 37 38 func (s Store) key(key []byte) (res []byte) { 39 if key == nil { 40 panic("nil key on Store") 41 } 42 res = cloneAppend(s.prefix, key) 43 return 44 } 45 46 // Implements Store 47 func (s Store) GetStoreType() types.StoreType { 48 return s.parent.GetStoreType() 49 } 50 51 // Implements CacheWrap 52 func (s Store) CacheWrap() types.CacheWrap { 53 return cachekv.NewStore(s) 54 } 55 56 // CacheWrapWithTrace implements the KVStore interface. 57 func (s Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { 58 return cachekv.NewStore(tracekv.NewStore(s, w, tc)) 59 } 60 61 // CacheWrapWithListeners implements the CacheWrapper interface. 62 func (s Store) CacheWrapWithListeners(storeKey types.StoreKey, listeners []types.WriteListener) types.CacheWrap { 63 return cachekv.NewStore(listenkv.NewStore(s, storeKey, listeners)) 64 } 65 66 // Implements KVStore 67 func (s Store) Get(key []byte) []byte { 68 res := s.parent.Get(s.key(key)) 69 return res 70 } 71 72 // Implements KVStore 73 func (s Store) Has(key []byte) bool { 74 return s.parent.Has(s.key(key)) 75 } 76 77 // Implements KVStore 78 func (s Store) Set(key, value []byte) { 79 types.AssertValidKey(key) 80 types.AssertValidValue(value) 81 s.parent.Set(s.key(key), value) 82 } 83 84 // Implements KVStore 85 func (s Store) Delete(key []byte) { 86 s.parent.Delete(s.key(key)) 87 } 88 89 // Implements KVStore 90 // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106 91 func (s Store) Iterator(start, end []byte) types.Iterator { 92 newstart := cloneAppend(s.prefix, start) 93 94 var newend []byte 95 if end == nil { 96 newend = cpIncr(s.prefix) 97 } else { 98 newend = cloneAppend(s.prefix, end) 99 } 100 101 iter := s.parent.Iterator(newstart, newend) 102 103 return newPrefixIterator(s.prefix, start, end, iter) 104 } 105 106 // ReverseIterator implements KVStore 107 // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L129 108 func (s Store) ReverseIterator(start, end []byte) types.Iterator { 109 newstart := cloneAppend(s.prefix, start) 110 111 var newend []byte 112 if end == nil { 113 newend = cpIncr(s.prefix) 114 } else { 115 newend = cloneAppend(s.prefix, end) 116 } 117 118 iter := s.parent.ReverseIterator(newstart, newend) 119 120 return newPrefixIterator(s.prefix, start, end, iter) 121 } 122 123 var _ types.Iterator = (*prefixIterator)(nil) 124 125 type prefixIterator struct { 126 prefix []byte 127 start []byte 128 end []byte 129 iter types.Iterator 130 valid bool 131 } 132 133 func newPrefixIterator(prefix, start, end []byte, parent types.Iterator) *prefixIterator { 134 return &prefixIterator{ 135 prefix: prefix, 136 start: start, 137 end: end, 138 iter: parent, 139 valid: parent.Valid() && bytes.HasPrefix(parent.Key(), prefix), 140 } 141 } 142 143 // Implements Iterator 144 func (pi *prefixIterator) Domain() ([]byte, []byte) { 145 return pi.start, pi.end 146 } 147 148 // Implements Iterator 149 func (pi *prefixIterator) Valid() bool { 150 return pi.valid && pi.iter.Valid() 151 } 152 153 // Implements Iterator 154 func (pi *prefixIterator) Next() { 155 if !pi.valid { 156 panic("prefixIterator invalid, cannot call Next()") 157 } 158 159 if pi.iter.Next(); !pi.iter.Valid() || !bytes.HasPrefix(pi.iter.Key(), pi.prefix) { 160 // TODO: shouldn't pi be set to nil instead? 161 pi.valid = false 162 } 163 } 164 165 // Implements Iterator 166 func (pi *prefixIterator) Key() (key []byte) { 167 if !pi.valid { 168 panic("prefixIterator invalid, cannot call Key()") 169 } 170 171 key = pi.iter.Key() 172 key = stripPrefix(key, pi.prefix) 173 174 return 175 } 176 177 // Implements Iterator 178 func (pi *prefixIterator) Value() []byte { 179 if !pi.valid { 180 panic("prefixIterator invalid, cannot call Value()") 181 } 182 183 return pi.iter.Value() 184 } 185 186 // Implements Iterator 187 func (pi *prefixIterator) Close() error { 188 return pi.iter.Close() 189 } 190 191 // Error returns an error if the prefixIterator is invalid defined by the Valid 192 // method. 193 func (pi *prefixIterator) Error() error { 194 if !pi.Valid() { 195 return errors.New("invalid prefixIterator") 196 } 197 198 return nil 199 } 200 201 // copied from github.com/tendermint/tendermint/libs/db/prefix_db.go 202 func stripPrefix(key []byte, prefix []byte) []byte { 203 if len(key) < len(prefix) || !bytes.Equal(key[:len(prefix)], prefix) { 204 panic("should not happen") 205 } 206 207 return key[len(prefix):] 208 } 209 210 // wrapping types.PrefixEndBytes 211 func cpIncr(bz []byte) []byte { 212 return types.PrefixEndBytes(bz) 213 }