OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / go-wire / data / README.md
1
2
3 # data
4 `import "github.com/tendermint/go-wire/data"`
5
6 * [Overview](#pkg-overview)
7 * [Index](#pkg-index)
8
9 ## <a name="pkg-overview">Overview</a>
10 Data is designed to provide a standard interface and helper functions to
11 easily allow serialization and deserialization of your data structures
12 in both binary and json representations.
13
14 This is commonly needed for interpreting transactions or stored data in the
15 abci app, as well as accepting json input in the light-client proxy. If we
16 can standardize how we pass data around the app, we can also allow more
17 extensions, like data storage that can interpret the meaning of the []byte
18 passed in, and use that to index multiple fields for example.
19
20 Serialization of data is pretty automatic using standard json and go-wire
21 encoders.  The main issue is deserialization, especially when using interfaces
22 where there are many possible concrete types.
23
24 go-wire handles this by registering the types and providing a custom
25 deserializer:
26
27
28         var _ = wire.RegisterInterface(
29           struct{ PubKey }{},
30           wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519},
31           wire.ConcreteType{PubKeySecp256k1{}, PubKeyTypeSecp256k1},
32         )
33         
34         func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) {
35           err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey)
36           return
37         }
38         
39         func (pubKey PubKeyEd25519) Bytes() []byte {
40           return wire.BinaryBytes(struct{ PubKey }{pubKey})
41         }
42
43 This prepends a type-byte to the binary representation upon serialization and
44 using that byte to switch between various representations on deserialization.
45 go-wire also supports something similar in json, but it leads to kind of ugly
46 mixed-types arrays, and requires using the go-wire json parser, which is
47 limited relative to the standard library encoding/json library.
48
49 In json, the typical idiom is to use a type string and message data:
50
51
52         {
53           "type": "this part tells you how to interpret the message",
54           "data": ...the actual message is here, in some kind of json...
55         }
56
57 I took inspiration from two blog posts, that demonstrate how to use this
58 to build (de)serialization in a go-wire like way.
59
60 * <a href="http://eagain.net/articles/go-dynamic-json/">http://eagain.net/articles/go-dynamic-json/</a>
61 * <a href="http://eagain.net/articles/go-json-kind/">http://eagain.net/articles/go-json-kind/</a>
62
63 This package unifies these two in a single Mapper.
64
65 You app needs to do three things to take full advantage of this:
66
67 1. For every interface you wish to serialize, define a holder struct with some helper methods, like FooerS wraps Fooer in common_test.go
68 2. In all structs that include this interface, include the wrapping struct instead.  Functionally, this also fulfills the interface, so except for setting it or casting it to a sub-type it works the same.
69 3. Register the interface implementations as in the last init of common_test.go. If you are currently using go-wire, you should be doing this already
70
71 The benefits here is you can now run any of the following methods, both for
72 efficient storage in our go app, and a common format for rpc / humans.
73
74
75         orig := FooerS{foo}
76         
77         // read/write binary a la tendermint/go-wire
78         bparsed := FooerS{}
79         err := wire.ReadBinaryBytes(
80           wire.BinaryBytes(orig), &bparsed)
81         
82         // read/write json a la encoding/json
83         jparsed := FooerS{}
84         j, err := json.MarshalIndent(orig, "", "\t")
85         err = json.Unmarshal(j, &jparsed)
86
87 See <a href="https://github.com/tendermint/go-wire/data/blob/master/common_test.go">https://github.com/tendermint/go-wire/data/blob/master/common_test.go</a> to see
88 how to set up your code to use this.
89
90
91
92
93 ## <a name="pkg-index">Index</a>
94 * [Variables](#pkg-variables)
95 * [type ByteEncoder](#ByteEncoder)
96 * [type Bytes](#Bytes)
97   * [func (b Bytes) MarshalJSON() ([]byte, error)](#Bytes.MarshalJSON)
98   * [func (b *Bytes) UnmarshalJSON(data []byte) error](#Bytes.UnmarshalJSON)
99 * [type JSONMapper](#JSONMapper)
100   * [func (m *JSONMapper) FromJSON(data []byte) (interface{}, error)](#JSONMapper.FromJSON)
101   * [func (m *JSONMapper) ToJSON(data interface{}) ([]byte, error)](#JSONMapper.ToJSON)
102 * [type Mapper](#Mapper)
103   * [func NewMapper(base interface{}) Mapper](#NewMapper)
104   * [func (m Mapper) RegisterInterface(kind string, b byte, data interface{}) Mapper](#Mapper.RegisterInterface)
105
106
107 #### <a name="pkg-files">Package files</a>
108 [binary.go](/src/github.com/tendermint/go-wire/data/binary.go) [bytes.go](/src/github.com/tendermint/go-wire/data/bytes.go) [docs.go](/src/github.com/tendermint/go-wire/data/docs.go) [json.go](/src/github.com/tendermint/go-wire/data/json.go) [wrapper.go](/src/github.com/tendermint/go-wire/data/wrapper.go) 
109
110
111
112 ## <a name="pkg-variables">Variables</a>
113 ``` go
114 var (
115     Encoder       ByteEncoder = hexEncoder{}
116     HexEncoder                = hexEncoder{}
117     B64Encoder                = base64Encoder{base64.URLEncoding}
118     RawB64Encoder             = base64Encoder{base64.RawURLEncoding}
119 )
120 ```
121 Encoder is a global setting for all byte encoding
122 This is the default.  Please override in the main()/init()
123 of your program to change how byte slices are presented
124
125
126
127
128 ## <a name="ByteEncoder">type</a> [ByteEncoder](/src/target/bytes.go?s=1436:1547#L44)
129 ``` go
130 type ByteEncoder interface {
131     Marshal(bytes []byte) ([]byte, error)
132     Unmarshal(dst *[]byte, src []byte) error
133 }
134 ```
135 ByteEncoder handles both the marshalling and unmarshalling of
136 an arbitrary byte slice.
137
138 All Bytes use the global Encoder set in this package.
139 If you want to use this encoding for byte arrays, you can just
140 implement a simple custom marshaller for your byte array
141
142
143         type Dings [64]byte
144         
145         func (d Dings) MarshalJSON() ([]byte, error) {
146           return data.Encoder.Marshal(d[:])
147         }
148         
149         func (d *Dings) UnmarshalJSON(data []byte) error {
150           ref := (*d)[:]
151           return data.Encoder.Unmarshal(&ref, data)
152         }
153
154
155
156
157
158
159
160
161
162
163 ## <a name="Bytes">type</a> [Bytes](/src/target/bytes.go?s=681:698#L16)
164 ``` go
165 type Bytes []byte
166 ```
167 Bytes is a special byte slice that allows us to control the
168 serialization format per app.
169
170 Thus, basecoin could use hex, another app base64, and a third
171 app base58...
172
173
174
175
176
177
178
179
180
181
182 ### <a name="Bytes.MarshalJSON">func</a> (Bytes) [MarshalJSON](/src/target/bytes.go?s=700:744#L18)
183 ``` go
184 func (b Bytes) MarshalJSON() ([]byte, error)
185 ```
186
187
188
189 ### <a name="Bytes.UnmarshalJSON">func</a> (\*Bytes) [UnmarshalJSON](/src/target/bytes.go?s=777:825#L22)
190 ``` go
191 func (b *Bytes) UnmarshalJSON(data []byte) error
192 ```
193
194
195
196 ## <a name="JSONMapper">type</a> [JSONMapper](/src/target/json.go?s=80:178#L1)
197 ``` go
198 type JSONMapper struct {
199     // contains filtered or unexported fields
200 }
201 ```
202
203
204
205
206
207
208
209
210
211 ### <a name="JSONMapper.FromJSON">func</a> (\*JSONMapper) [FromJSON](/src/target/json.go?s=1202:1265#L41)
212 ``` go
213 func (m *JSONMapper) FromJSON(data []byte) (interface{}, error)
214 ```
215 FromJSON will deserialize the output of ToJSON for every registered
216 implementation of the interface
217
218
219
220
221 ### <a name="JSONMapper.ToJSON">func</a> (\*JSONMapper) [ToJSON](/src/target/json.go?s=1814:1875#L67)
222 ``` go
223 func (m *JSONMapper) ToJSON(data interface{}) ([]byte, error)
224 ```
225 ToJson will serialize a registered implementation into a format like:
226
227
228         {
229           "type": "foo",
230           "data": {
231             "name": "dings"
232           }
233         }
234
235 this allows us to properly deserialize with FromJSON
236
237
238
239
240 ## <a name="Mapper">type</a> [Mapper](/src/target/wrapper.go?s=485:535#L5)
241 ``` go
242 type Mapper struct {
243     *JSONMapper
244     // contains filtered or unexported fields
245 }
246 ```
247 Mapper is the main entry point in the package.
248
249 On init, you should call NewMapper() for each interface type you want
250 to support flexible de-serialization, and then
251 RegisterInterface() in the init() function for each implementation of these
252 interfaces.
253
254 Note that unlike go-wire, you can call RegisterInterface separately from
255 different locations with each implementation, not all in one place.
256 Just be careful not to use the same key or byte, of init will *panic*
257
258
259
260
261
262
263
264 ### <a name="NewMapper">func</a> [NewMapper](/src/target/wrapper.go?s=747:786#L17)
265 ``` go
266 func NewMapper(base interface{}) Mapper
267 ```
268 NewMapper creates a Mapper.
269
270 If you have:
271
272
273         type Foo interface {....}
274         type FooS struct { Foo }
275
276 then you should pass in FooS{} in NewMapper, and implementations of Foo
277 in RegisterInterface
278
279
280
281
282
283 ### <a name="Mapper.RegisterInterface">func</a> (Mapper) [RegisterInterface](/src/target/wrapper.go?s=1184:1263#L30)
284 ``` go
285 func (m Mapper) RegisterInterface(kind string, b byte, data interface{}) Mapper
286 ```
287 RegisterInterface should be called once for each implementation of the
288 interface that we wish to support.
289
290 kind is the type string used in the json representation, while b is the
291 type byte used in the go-wire representation. data is one instance of this
292 concrete type, like Bar{}
293
294
295
296
297
298
299
300
301 - - -
302 Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)