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  }