/
codec.go
139 lines (120 loc) · 3.82 KB
/
codec.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
// Go Substrate RPC Client (GSRPC) provides APIs and types around Polkadot and any Substrate-based chain RPC calls
//
// Copyright 2019 Centrifuge GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"bytes"
"encoding/hex"
"fmt"
"reflect"
"strings"
"github.com/rjman-self/centrifuge-substrate-rpc/v3/scale"
"golang.org/x/crypto/blake2b"
)
// Hexer interface is implemented by any type that has a Hex() function returning a string
type Hexer interface {
Hex() string
}
// EncodeToBytes encodes `value` with the scale codec with passed EncoderOptions, returning []byte
// TODO rename to Encode
func EncodeToBytes(value interface{}) ([]byte, error) {
var buffer = bytes.Buffer{}
err := scale.NewEncoder(&buffer).Encode(value)
if err != nil {
return buffer.Bytes(), err
}
return buffer.Bytes(), nil
}
// EncodeToHexString encodes `value` with the scale codec, returning a hex string (prefixed by 0x)
// TODO rename to EncodeToHex
func EncodeToHexString(value interface{}) (string, error) {
bz, err := EncodeToBytes(value)
if err != nil {
return "", err
}
return fmt.Sprintf("%#x", bz), nil
}
// DecodeFromBytes decodes `bz` with the scale codec into `target`. `target` should be a pointer.
// TODO rename to Decode
func DecodeFromBytes(bz []byte, target interface{}) error {
return scale.NewDecoder(bytes.NewReader(bz)).Decode(target)
}
// DecodeFromHexString decodes `str` with the scale codec into `target`. `target` should be a pointer.
// TODO rename to DecodeFromHex
func DecodeFromHexString(str string, target interface{}) error {
bz, err := HexDecodeString(str)
if err != nil {
return err
}
return DecodeFromBytes(bz, target)
}
// EncodedLength returns the length of the value when encoded as a byte array
func EncodedLength(value interface{}) (int, error) {
var buffer = bytes.Buffer{}
err := scale.NewEncoder(&buffer).Encode(value)
if err != nil {
return 0, err
}
return buffer.Len(), nil
}
// GetHash returns a hash of the value
func GetHash(value interface{}) (Hash, error) {
enc, err := EncodeToBytes(value)
if err != nil {
return Hash{}, err
}
return blake2b.Sum256(enc), err
}
// Eq compares the value of the input to see if there is a match
func Eq(one, other interface{}) bool {
return reflect.DeepEqual(one, other)
}
// HexDecodeString decodes bytes from a hex string. Contrary to hex.DecodeString, this function does not error if "0x"
// is prefixed, and adds an extra 0 if the hex string has an odd length.
func HexDecodeString(s string) ([]byte, error) {
s = strings.TrimPrefix(s, "0x")
if len(s)%2 != 0 {
s = "0" + s
}
b, err := hex.DecodeString(s)
if err != nil {
return nil, err
}
return b, nil
}
// MustHexDecodeString panics if str cannot be decoded
func MustHexDecodeString(str string) []byte {
bz, err := HexDecodeString(str)
if err != nil {
panic(err)
}
return bz
}
// HexEncode encodes bytes to a hex string. Contrary to hex.EncodeToString, this function prefixes the hex string
// with "0x"
func HexEncodeToString(b []byte) string {
return "0x" + hex.EncodeToString(b)
}
// Hex returns a hex string representation of the value (not of the encoded value)
func Hex(value interface{}) (string, error) {
switch v := value.(type) {
case Hexer:
return v.Hex(), nil
case []byte:
return fmt.Sprintf("%#x", v), nil
default:
return "", fmt.Errorf("does not support %T", v)
}
}