github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/list/list.go (about) 1 package list 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 8 9 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types" 10 ) 11 12 // Key for the length of the list 13 func LengthKey() []byte { 14 return []byte{0x00} 15 } 16 17 // Key for the elements of the list 18 func ElemKey(index uint64) []byte { 19 return append([]byte{0x01}, []byte(fmt.Sprintf("%020d", index))...) 20 } 21 22 // List defines an integer indexable mapper 23 // It panics when the element type cannot be (un/)marshalled by the codec 24 type List struct { 25 cdc *codec.Codec 26 store types.KVStore 27 } 28 29 // NewList constructs new List 30 func NewList(cdc *codec.Codec, store types.KVStore) List { 31 return List{ 32 cdc: cdc, 33 store: store, 34 } 35 } 36 37 // Len() returns the length of the list 38 // The length is only increased by Push() and not decreased 39 // List dosen't check if an index is in bounds 40 // The user should check Len() before doing any actions 41 func (m List) Len() (res uint64) { 42 bz := m.store.Get(LengthKey()) 43 if bz == nil { 44 return 0 45 } 46 47 m.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &res) 48 return 49 } 50 51 // Get() returns the element by its index 52 func (m List) Get(index uint64, ptr interface{}) error { 53 bz := m.store.Get(ElemKey(index)) 54 return m.cdc.UnmarshalBinaryLengthPrefixed(bz, ptr) 55 } 56 57 // Set() stores the element to the given position 58 // Setting element out of range will break length counting 59 // Use Push() instead of Set() to append a new element 60 func (m List) Set(index uint64, value interface{}) { 61 bz := m.cdc.MustMarshalBinaryLengthPrefixed(value) 62 m.store.Set(ElemKey(index), bz) 63 } 64 65 // Delete() deletes the element in the given position 66 // Other elements' indices are preserved after deletion 67 // Panics when the index is out of range 68 func (m List) Delete(index uint64) { 69 m.store.Delete(ElemKey(index)) 70 } 71 72 // Push() inserts the element to the end of the list 73 // It will increase the length when it is called 74 func (m List) Push(value interface{}) { 75 length := m.Len() 76 m.Set(length, value) 77 m.store.Set(LengthKey(), m.cdc.MustMarshalBinaryLengthPrefixed(length+1)) 78 } 79 80 // Iterate() is used to iterate over all existing elements in the list 81 // Return true in the continuation to break 82 // The second element of the continuation will indicate the position of the element 83 // Using it with Get() will return the same one with the provided element 84 85 // CONTRACT: No writes may happen within a domain while iterating over it. 86 func (m List) Iterate(ptr interface{}, fn func(uint64) bool) { 87 iter := types.KVStorePrefixIterator(m.store, []byte{0x01}) 88 defer iter.Close() 89 for ; iter.Valid(); iter.Next() { 90 v := iter.Value() 91 m.cdc.MustUnmarshalBinaryLengthPrefixed(v, ptr) 92 93 k := iter.Key() 94 s := string(k[len(k)-20:]) 95 96 index, err := strconv.ParseUint(s, 10, 64) 97 if err != nil { 98 panic(err) 99 } 100 101 if fn(index) { 102 break 103 } 104 } 105 }