OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / go-wire / README.md
1 # Wire encoding for Golang
2
3 This software implements Go bindings for the Wire encoding protocol.
4 The goal of the Wire encoding protocol is to be a simple language-agnostic encoding protocol for rapid prototyping of blockchain applications.
5
6 This package also includes a compatible (and slower) JSON codec.
7
8 ### Supported types
9
10 **Primary types**: `uvarint`, `varint`, `byte`, `uint[8,16,32,64]`, `int[8,16,32,64]`, `string`, and `time` types are supported
11
12 **Arrays**: Arrays can hold items of any arbitrary type.  For example, byte-arrays and byte-array-arrays are supported.
13
14 **Structs**: Struct fields are encoded by value (without the key name) in the order that they are declared in the struct.  In this way it is similar to Apache Avro.
15
16 **Interfaces**: Interfaces are like union types where the value can be any non-interface type. The actual value is preceded by a single "type byte" that shows which concrete is encoded.
17
18 **Pointers**: Pointers are like optional fields.  The first byte is 0x00 to denote a null pointer (e.g. no value), otherwise it is 0x01.
19
20 ### Unsupported types
21
22 **Maps**: Maps are not supported because for most languages, key orders are nondeterministic.
23 If you need to encode/decode maps of arbitrary key-value pairs, encode an array of {key,value} structs instead.
24
25 **Floating points**: Floating point number types are discouraged because [of reasons](http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/).  If you need to use them, use the field tag `wire:"unsafe"`.
26
27 **Enums**: Enum types are not supported in all languages, and they're simple enough to model as integers anyways.
28
29 ### A struct example
30
31 Struct types can be automatically encoded with reflection.  Unlike json-encoding, no field
32 name or type information is encoded.  Field values are simply encoded in order.
33
34 ```go
35 package main
36
37 import (
38   "bytes"
39   "fmt"
40   "math"
41   "github.com/tendermint/go-wire"
42 )
43
44 type Foo struct {
45   MyString       string
46   MyUint32       uint32
47   myPrivateBytes []byte
48 }
49
50 func main() {
51
52   foo := Foo{"my string", math.MaxUint32, []byte("my private bytes")}
53
54   buf, n, err := new(bytes.Buffer), int(0), error(nil)
55   wire.WriteBinary(foo, buf, &n, &err)
56
57   fmt.Printf("%X\n", buf.Bytes())
58 }
59 ```
60
61 The above example prints:
62
63 ```
64 01096D7920737472696E67FFFFFFFF, where
65
66 0109                            is the varint encoding of the length of string "my string"
67     6D7920737472696E67          is the bytes of string "my string"
68                       FFFFFFFF  is the bytes for math.MaxUint32, a uint32
69 ```
70
71 Note that the unexported "myPrivateBytes" isn't encoded.
72
73 ### An interface example
74
75 Here's an example with interfaces.
76
77 ```go
78 package main
79
80 import (
81   "bytes"
82   "fmt"
83   "github.com/tendermint/go-wire"
84 )
85
86 type Animal interface{}
87 type Dog struct{ Name string }
88 type Cat struct{ Name string }
89 type Cow struct{ Name string }
90
91 var _ = wire.RegisterInterface(
92   struct{ Animal }{},
93   wire.ConcreteType{Dog{}, 0x01}, // type-byte of 0x01 for Dogs
94   wire.ConcreteType{Cat{}, 0x02}, // type-byte of 0x02 for Cats
95   wire.ConcreteType{Cow{}, 0x03}, // type-byte of 0x03 for Cows
96 )
97
98 func main() {
99
100   animals := []Animal{
101     Dog{"Snoopy"},
102     Cow{"Daisy"},
103   }
104
105   buf, n, err := new(bytes.Buffer), int(0), error(nil)
106   wire.WriteBinary(animals, buf, &n, &err)
107
108   fmt.Printf("%X\n", buf.Bytes())
109 }
110 ```
111
112 The above example prints:
113
114 ```
115 0102010106536E6F6F70790301054461697379, where
116
117 0102                                    is the varint encoding of the length of the array
118     01                                  is the type-byte for a Dog
119       0106                              is the varint encoding of the length of the Dog's name
120           536E6F6F7079                  is the Dog's name "Snoopy"
121                       03                is the type-byte for a Cow
122                         0105            is the varint encoding of the length of the Cow's name
123                             4461697379  is the Cow's name "Daisy"
124 ```
125
126 ### A pointer example
127
128 Here's an example with pointers (and interfaces too).
129
130 ```go
131 package main
132
133 import (
134         "bytes"
135         "fmt"
136         "github.com/tendermint/go-wire"
137 )
138
139 type Animal interface{}
140 type Dog struct{ Name string }
141 type Cat struct{ Name string }
142 type Cow struct{ Name string }
143
144 var _ = wire.RegisterInterface(
145         struct{ Animal }{},
146         wire.ConcreteType{Dog{}, 0x01},  // type-byte of 0x01 for Dogs
147         wire.ConcreteType{&Dog{}, 0x02}, // type-byte of 0x02 for Dog pointers
148 )
149
150 type MyStruct struct {
151         Field1 Animal
152         Field2 *Dog
153         Field3 *Dog
154 }
155
156 func main() {
157
158         myStruct := MyStruct{
159                 Field1: &Dog{"Snoopy"},
160                 Field2: &Dog{"Smappy"},
161                 Field3: (*Dog)(nil),
162         }
163
164         buf, n, err := new(bytes.Buffer), int(0), error(nil)
165         wire.WriteBinary(myStruct, buf, &n, &err)
166
167         fmt.Printf("%X\n", buf.Bytes())
168 }
169 ```
170
171 The above example prints:
172
173 ```
174 020106536E6F6F7079010106536D6170707900, where
175
176 02                                      is the type-byte for a Dog pointer for Field1
177   0106                                  is the varint encoding of the length of the Dog's name
178       536E6F6F7079                      is the Dog's name "Snoopy"
179                   01                    is a byte indicating a non-null pointer for Field2
180                     0106                is the varint encoding of the length of the Dog's name
181                         536D61707079    is the Dog's name "Smappy"
182                                     00  is a byte indicating a null pointer for Field3
183 ```
184
185 Notice that in Field1, that the value is non-null is implied in the type-byte of 0x02.
186 While Golang lets you have nil-pointers as interface values, this is a Golang-specific feature that is absent in other OOP languages
187 such as Java.  So, Go-Wire does not support nil-pointers for interface values.  The following example would return an error:
188
189 ```go
190 myStruct := MyStruct{
191   Field1: (*Dog)(nil),    // Error!
192   Field2: &Dog{"Smappy"}, // Ok!
193   Field3: (*Dog)(nil),    // Ok!
194 }
195
196 buf, n, err := new(bytes.Buffer), int(0), error(nil)
197 wire.WriteBinary(myStruct, buf, &n, &err)
198 fmt.Println(err)
199
200 // Unexpected nil-pointer of type main.Dog for registered interface Animal.
201 // For compatibility with other languages, nil-pointer interface values are forbidden.
202 ```