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  }