github.com/s7techlab/cckit@v0.10.5/state/key.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 8 "github.com/hyperledger/fabric-chaincode-go/shim" 9 10 "github.com/s7techlab/cckit/convert" 11 ) 12 13 // StringsIdToStr helper for passing []string key 14 func StringsIdToStr(idSlice []string) string { 15 return strings.Join(idSlice, "\000") 16 } 17 18 // StringsIdFromStr helper for restoring []string key 19 func StringsIdFromStr(idString string) []string { 20 return strings.Split(idString, "\000") 21 } 22 23 type ( 24 Key []string 25 26 // StateKey stores origin and transformed state key 27 TransformedKey struct { 28 Origin Key 29 Parts Key 30 String string 31 } 32 33 //KeyerFunc func(string) ([]string, error) 34 KeyFunc func() (Key, error) 35 36 // KeyerFunc transforms string to key 37 KeyerFunc func(string) (Key, error) 38 39 // Keyer interface for entity containing logic of its key creation 40 Keyer interface { 41 Key() (Key, error) 42 } 43 44 // StringsKeys interface for entity containing logic of its key creation - backward compatibility 45 StringsKeyer interface { 46 Key() ([]string, error) 47 } 48 49 // KeyValue interface combines Keyer as ToByter methods - state entry representation 50 KeyValue interface { 51 Keyer 52 convert.ToByter 53 } 54 55 stringKeyer struct { 56 str string 57 keyer KeyerFunc 58 } 59 ) 60 61 func (k Key) Append(key Key) Key { 62 return append(k, key...) 63 } 64 65 // Key human readable representation 66 func (k Key) String() string { 67 return strings.Join(k, ` | `) 68 } 69 70 // Parts returns object type and attributes slice 71 func (k Key) Parts() (objectType string, attrs []string) { 72 if len(k) > 0 { 73 objectType = k[0] 74 75 if len(k) > 1 { 76 attrs = k[1:] 77 } 78 } 79 return 80 } 81 82 func NormalizeKey(stub shim.ChaincodeStubInterface, key interface{}) (Key, error) { 83 switch k := key.(type) { 84 case Key: 85 return k, nil 86 case Keyer: 87 return k.Key() 88 case StringsKeyer: 89 return k.Key() 90 case string: 91 return KeyFromComposite(stub, k) 92 case []string: 93 return k, nil 94 } 95 return nil, fmt.Errorf(`%s: %w`, reflect.TypeOf(key), ErrUnableToCreateStateKey) 96 } 97 98 func KeyFromComposite(stub shim.ChaincodeStubInterface, key string) (Key, error) { 99 var ( 100 objectType string 101 attributes []string 102 err error 103 ) 104 105 // contains key delimiter 106 if strings.ContainsRune(key, 0) { 107 objectType, attributes, err = stub.SplitCompositeKey(key) 108 if err != nil { 109 return nil, fmt.Errorf(`key from composite: %w`, err) 110 } 111 } else { 112 objectType = key 113 } 114 115 return append([]string{objectType}, attributes...), nil 116 } 117 118 func KeyToComposite(stub shim.ChaincodeStubInterface, key Key) (string, error) { 119 compositeKey, err := stub.CreateCompositeKey(key[0], key[1:]) 120 if err != nil { 121 return ``, fmt.Errorf(`key to composite: %w`, err) 122 } 123 124 return compositeKey, nil 125 } 126 127 func KeyToString(stub shim.ChaincodeStubInterface, key Key) (string, error) { 128 switch len(key) { 129 case 0: 130 return ``, ErrKeyPartsLength 131 case 1: 132 return key[0], nil 133 default: 134 return KeyToComposite(stub, key) 135 } 136 } 137 138 func (sk stringKeyer) Key() (Key, error) { 139 return sk.keyer(sk.str) 140 } 141 142 // StringKeyer constructor for struct implementing Keyer interface 143 func StringKeyer(str string, keyer KeyerFunc) Keyer { 144 return stringKeyer{str, keyer} 145 }