You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
3.8 KiB

10 years ago
10 years ago
  1. ### NOTICE
  2. This documentation is out of date.
  3. * 0x00 is reserved as a nil byte for RegisterInterface
  4. * moved TypeByte() into RegisterInterface/ConcreteType
  5. # `tendermint/binary`
  6. The `binary` submodule encodes primary types and structs into bytes.
  7. ## Primary types
  8. uint\*, int\*, string, time, byteslice and byteslice-slice types can be
  9. encoded and decoded with the following methods:
  10. The following writes `o uint64` to `w io.Writer`, and increments `n` and/or sets `err`
  11. ```go
  12. WriteUint64(o uint64, w io.Writer, n *int64, err *error)
  13. // Typical usage:
  14. buf, n, err := new(bytes.Buffer), new(int64), new(error)
  15. WriteUint64(uint64(x), buf, n, err)
  16. if *err != nil {
  17. panic(err)
  18. }
  19. ```
  20. The following reads a `uint64` from `r io.Reader`, and increments `n` and/or sets `err`
  21. ```go
  22. var o = ReadUint64(r io.Reader, n *int64, err *error)
  23. ```
  24. Similar methods for `uint32`, `uint16`, `uint8`, `int64`, `int32`, `int16`, `int8` exist.
  25. Protobuf variable length encoding is done with `uint` and `int` types:
  26. ```go
  27. WriteUvarint(o uint, w io.Writer, n *int64, err *error)
  28. var o = ReadUvarint(r io.Reader, n *int64, err *error)
  29. ```
  30. Byteslices can be written with:
  31. ```go
  32. WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error)
  33. ```
  34. Byteslices (and all slices such as byteslice-slices) are prepended with
  35. `uvarint` encoded length, so `ReadByteSlice()` knows how many bytes to read.
  36. Note that there is no type information encoded -- the caller is assumed to know what types
  37. to decode.
  38. ## Struct Types
  39. Struct types can be automatically encoded with reflection. Unlike json-encoding, no field
  40. name or type information is encoded. Field values are simply encoded in order.
  41. ```go
  42. type Foo struct {
  43. MyString string
  44. MyUint32 uint32
  45. myPrivateBytes []byte
  46. }
  47. foo := Foo{"my string", math.MaxUint32, []byte("my private bytes")}
  48. buf, n, err := new(bytes.Buffer), new(int64), new(error)
  49. WriteBinary(foo, buf, n, err)
  50. // fmt.Printf("%X", buf.Bytes()) gives:
  51. // 096D7920737472696E67FFFFFFFF
  52. // 09: uvarint encoded length of string "my string"
  53. // 6D7920737472696E67: bytes of string "my string"
  54. // FFFFFFFF: bytes for MaxUint32
  55. // Note that the unexported "myPrivateBytes" isn't encoded.
  56. foo2 := ReadBinary(Foo{}, buf, n, err).(Foo)
  57. // Or, to decode onto a pointer:
  58. foo2 := ReadBinary(&Foo{}, buf, n, err).(*Foo)
  59. ```
  60. WriteBinary and ReadBinary can encode/decode structs recursively. However, interface field
  61. values are a bit more complicated.
  62. ```go
  63. type Greeter interface {
  64. Greet() string
  65. }
  66. type Dog struct{}
  67. func (d Dog) Greet() string { return "Woof!" }
  68. type Cat struct{}
  69. func (c Cat) Greet() string { return "Meow!" }
  70. type Foo struct {
  71. Greeter
  72. }
  73. foo := Foo{Dog{}}
  74. buf, n, err := new(bytes.Buffer), new(int64), new(error)
  75. WriteBinary(foo, buf, n, err)
  76. // This errors because we don't know whether to read a Dog or Cat.
  77. foo2 := ReadBinary(Foo{}, buf, n, err)
  78. ```
  79. In the above example, `ReadBinary()` fails because the `Greeter` field for `Foo{}`
  80. is ambiguous -- it could be either a `Dog{}` or a `Cat{}`, like a union structure.
  81. The solution is to declare the concrete implementation types for interfaces:
  82. ```go
  83. type Dog struct{}
  84. func (d Dog) TypeByte() byte { return GreeterTypeDog }
  85. func (d Dog) Greet() string { return "Woof!" }
  86. type Cat struct{}
  87. func (c Cat) TypeByte() byte { return GreeterTypeCat }
  88. func (c Cat) Greet() string { return "Meow!" }
  89. var _ = RegisterInterface(
  90. struct{Greeter}{},
  91. ConcreteType{Dog{}},
  92. ConcreteType{Cat{}},
  93. })
  94. ```
  95. NOTE: The TypeByte() is written and expected to be read even when the struct
  96. is encoded or decoded directly:
  97. ```go
  98. WriteBinary(Dog{}, buf, n, err) // Writes GreeterTypeDog byte
  99. dog_ := ReadBinary(Dog{}, buf, n, err) // Expects to read GreeterTypeDog byte
  100. dog := dog_.(Dog) // ok if *err != nil, otherwise dog_ == nil.
  101. ```