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