github.com/eris-ltd/erisdb@v0.25.0/storage/kvstore.go (about)

     1  package storage
     2  
     3  import (
     4  	"bytes"
     5  
     6  	dbm "github.com/tendermint/tendermint/libs/db"
     7  )
     8  
     9  type KVIterator = dbm.Iterator
    10  
    11  // This is partially extrated from Cosmos SDK for alignment but is more minimal, we should suggest this becomes an
    12  // embedded interface
    13  type KVIterable interface {
    14  	// Iterator over a domain of keys in ascending order. high is exclusive.
    15  	// low must be less than high, or the Iterator is invalid.
    16  	// Iterator must be closed by caller.
    17  	// To iterate over entire domain, use store.Iterator(nil, nil)
    18  	// CONTRACT: No writes may happen within a domain while an iterator exists over it.
    19  	Iterator(low, high []byte) KVIterator
    20  
    21  	// Iterator over a domain of keys in descending order. high is exclusive.
    22  	//  must be less than high, or the Iterator is invalid.
    23  	// Iterator must be closed by caller.
    24  	// CONTRACT: No writes may happen within a domain while an iterator exists over it.
    25  	ReverseIterator(low, high []byte) KVIterator
    26  }
    27  
    28  // Provides the native iteration for IAVLTree
    29  type KVCallbackIterable interface {
    30  	// low must be lexicographically less than high. high is exclusive unless it is nil in which case it is inclusive.
    31  	// ascending == false reverses order.
    32  	Iterate(low, high []byte, ascending bool, fn func(key []byte, value []byte) error) error
    33  }
    34  
    35  func KVCallbackIterator(rit KVCallbackIterable, ascending bool, low, high []byte) dbm.Iterator {
    36  	ch := make(chan KVPair)
    37  	go func() {
    38  		defer close(ch)
    39  		rit.Iterate(low, high, ascending, func(key, value []byte) (err error) {
    40  			ch <- KVPair{key, value}
    41  			return
    42  		})
    43  	}()
    44  	return NewChannelIterator(ch, low, high)
    45  }
    46  
    47  type KVReader interface {
    48  	// Get returns nil iff key doesn't exist. Panics on nil key.
    49  	Get(key []byte) []byte
    50  	// Has checks if a key exists. Panics on nil key.
    51  	Has(key []byte) bool
    52  }
    53  
    54  type KVWriter interface {
    55  	// Set sets the key. Panics on nil key.
    56  	Set(key, value []byte)
    57  	// Delete deletes the key. Panics on nil key.
    58  	Delete(key []byte)
    59  }
    60  
    61  type KVIterableReader interface {
    62  	KVReader
    63  	KVIterable
    64  }
    65  
    66  type KVCallbackIterableReader interface {
    67  	KVReader
    68  	KVCallbackIterable
    69  }
    70  
    71  // KVStore is a simple interface to get/set data
    72  type KVReaderWriter interface {
    73  	KVReader
    74  	KVWriter
    75  }
    76  
    77  type KVStore interface {
    78  	KVReaderWriter
    79  	KVIterable
    80  }
    81  
    82  // NormaliseDomain encodes the assumption that when nil is used as a lower bound is interpreted as low rather than high
    83  func NormaliseDomain(low, high []byte) ([]byte, []byte) {
    84  	if len(low) == 0 {
    85  		low = []byte{}
    86  	}
    87  	return low, high
    88  }
    89  
    90  // KeyOrder maps []byte{} -> -1, []byte(nil) -> 1, and everything else to 0. This encodes the assumptions of the
    91  // KVIterator domain endpoints
    92  func KeyOrder(key []byte) int {
    93  	if key == nil {
    94  		// Sup
    95  		return 1
    96  	}
    97  	if len(key) == 0 {
    98  		// Inf
    99  		return -1
   100  	}
   101  	// Normal key
   102  	return 0
   103  }
   104  
   105  // Sorts the keys as if they were compared lexicographically with their KeyOrder prepended
   106  func CompareKeys(k1, k2 []byte) int {
   107  	ko1 := KeyOrder(k1)
   108  	ko2 := KeyOrder(k2)
   109  	if ko1 < ko2 {
   110  		return -1
   111  	}
   112  	if ko1 > ko2 {
   113  		return 1
   114  	}
   115  	return bytes.Compare(k1, k2)
   116  }