OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / tendermint / go-wire / data / wrapper.go
1 package data
2
3 import "fmt"
4
5 /*
6 Mapper is the main entry point in the package.
7
8 On init, you should call NewMapper() for each interface type you want
9 to support flexible de-serialization, and then
10 RegisterImplementation() in the init() function for each implementation of these
11 interfaces.
12
13 Note that unlike go-wire, you can call RegisterImplementation separately from
14 different locations with each implementation, not all in one place.
15 Just be careful not to use the same key or byte, of init will *panic*
16 */
17 type Mapper struct {
18         *jsonMapper
19         *binaryMapper
20 }
21
22 // NewMapper creates a Mapper.
23 //
24 // If you have:
25 //   type Foo interface {....}
26 //   type FooS struct { Foo }
27 // then you should pass in FooS{} in NewMapper, and implementations of Foo
28 // in RegisterImplementation
29 func NewMapper(base interface{}) Mapper {
30         return Mapper{
31                 jsonMapper:   newJsonMapper(base),
32                 binaryMapper: newBinaryMapper(base),
33         }
34 }
35
36 // RegisterImplementation should be called once for each implementation of the
37 // interface that we wish to support.
38 //
39 // kind is the type string used in the json representation, while b is the
40 // type byte used in the go-wire representation. data is one instance of this
41 // concrete type, like Bar{}
42 func (m Mapper) RegisterImplementation(data interface{}, kind string, b byte) Mapper {
43         m.jsonMapper.registerImplementation(data, kind, b)
44         m.binaryMapper.registerImplementation(data, kind, b)
45         return m
46 }
47
48 // ToText is a rather special-case serialization for cli, especially for []byte
49 // interfaces
50 //
51 // It tries to serialize as json, and the result looks like:
52 //   { "type": "string", "data": "string" }
53 // Then it will return "<type>:<data>"
54 //
55 // Main usecase is serializing eg. crypto.PubKeyS as "ed25119:a1b2c3d4..."
56 // for displaying in cli tools.
57 //
58 // It also supports encoding data.Bytes to a string using the proper codec
59 // (or anything else that has a marshals to a string)
60 func ToText(o interface{}) (string, error) {
61         d, err := ToJSON(o)
62         if err != nil {
63                 return "", err
64         }
65
66         // try to recover as a string (data.Bytes case)
67         var s string
68         err = FromJSON(d, &s)
69         if err == nil {
70                 return s, nil
71         }
72
73         // if not, then try to recover as an interface (crypto.*S case)
74         text := textEnv{}
75         err = FromJSON(d, &text)
76         if err != nil {
77                 return "", err
78         }
79         res := fmt.Sprintf("%s:%s", text.Kind, text.Data)
80         return res, nil
81 }
82
83 // textEnv lets us parse an envelope if the data was output as string
84 // (either text, or a serialized []byte)
85 type textEnv struct {
86         Kind string `json:"type"`
87         Data string `json:"data"`
88 }