encoder.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package binary
  2. import (
  3. "encoding/binary"
  4. "io"
  5. "math"
  6. "reflect"
  7. "unsafe"
  8. )
  9. func NewEncoder(w io.Writer) *Encoder {
  10. return &Encoder{
  11. output: w,
  12. }
  13. }
  14. func NewEncoderWithCompress(w io.Writer) *Encoder {
  15. return &Encoder{
  16. output: w,
  17. compressOutput: NewCompressWriter(w),
  18. }
  19. }
  20. type Encoder struct {
  21. compress bool
  22. output io.Writer
  23. compressOutput io.Writer
  24. scratch [binary.MaxVarintLen64]byte
  25. }
  26. func (enc *Encoder) SelectCompress(compress bool) {
  27. if enc.compressOutput == nil {
  28. return
  29. }
  30. if enc.compress && !compress {
  31. enc.Flush()
  32. }
  33. enc.compress = compress
  34. }
  35. func (enc *Encoder) Get() io.Writer {
  36. if enc.compress && enc.compressOutput != nil {
  37. return enc.compressOutput
  38. }
  39. return enc.output
  40. }
  41. func (enc *Encoder) Uvarint(v uint64) error {
  42. ln := binary.PutUvarint(enc.scratch[:binary.MaxVarintLen64], v)
  43. if _, err := enc.Get().Write(enc.scratch[0:ln]); err != nil {
  44. return err
  45. }
  46. return nil
  47. }
  48. func (enc *Encoder) Bool(v bool) error {
  49. if v {
  50. return enc.UInt8(1)
  51. }
  52. return enc.UInt8(0)
  53. }
  54. func (enc *Encoder) Int8(v int8) error {
  55. return enc.UInt8(uint8(v))
  56. }
  57. func (enc *Encoder) Int16(v int16) error {
  58. return enc.UInt16(uint16(v))
  59. }
  60. func (enc *Encoder) Int32(v int32) error {
  61. return enc.UInt32(uint32(v))
  62. }
  63. func (enc *Encoder) Int64(v int64) error {
  64. return enc.UInt64(uint64(v))
  65. }
  66. func (enc *Encoder) UInt8(v uint8) error {
  67. enc.scratch[0] = v
  68. if _, err := enc.Get().Write(enc.scratch[:1]); err != nil {
  69. return err
  70. }
  71. return nil
  72. }
  73. func (enc *Encoder) UInt16(v uint16) error {
  74. enc.scratch[0] = byte(v)
  75. enc.scratch[1] = byte(v >> 8)
  76. if _, err := enc.Get().Write(enc.scratch[:2]); err != nil {
  77. return err
  78. }
  79. return nil
  80. }
  81. func (enc *Encoder) UInt32(v uint32) error {
  82. enc.scratch[0] = byte(v)
  83. enc.scratch[1] = byte(v >> 8)
  84. enc.scratch[2] = byte(v >> 16)
  85. enc.scratch[3] = byte(v >> 24)
  86. if _, err := enc.Get().Write(enc.scratch[:4]); err != nil {
  87. return err
  88. }
  89. return nil
  90. }
  91. func (enc *Encoder) UInt64(v uint64) error {
  92. enc.scratch[0] = byte(v)
  93. enc.scratch[1] = byte(v >> 8)
  94. enc.scratch[2] = byte(v >> 16)
  95. enc.scratch[3] = byte(v >> 24)
  96. enc.scratch[4] = byte(v >> 32)
  97. enc.scratch[5] = byte(v >> 40)
  98. enc.scratch[6] = byte(v >> 48)
  99. enc.scratch[7] = byte(v >> 56)
  100. if _, err := enc.Get().Write(enc.scratch[:8]); err != nil {
  101. return err
  102. }
  103. return nil
  104. }
  105. func (enc *Encoder) Float32(v float32) error {
  106. return enc.UInt32(math.Float32bits(v))
  107. }
  108. func (enc *Encoder) Float64(v float64) error {
  109. return enc.UInt64(math.Float64bits(v))
  110. }
  111. func (enc *Encoder) String(v string) error {
  112. str := Str2Bytes(v)
  113. if err := enc.Uvarint(uint64(len(str))); err != nil {
  114. return err
  115. }
  116. if _, err := enc.Get().Write(str); err != nil {
  117. return err
  118. }
  119. return nil
  120. }
  121. func (enc *Encoder) RawString(str []byte) error {
  122. if err := enc.Uvarint(uint64(len(str))); err != nil {
  123. return err
  124. }
  125. if _, err := enc.Get().Write(str); err != nil {
  126. return err
  127. }
  128. return nil
  129. }
  130. func (enc *Encoder) Decimal128(bytes []byte) error {
  131. _, err := enc.Get().Write(bytes)
  132. return err
  133. }
  134. func (enc *Encoder) Write(b []byte) (int, error) {
  135. return enc.Get().Write(b)
  136. }
  137. func (enc *Encoder) Flush() error {
  138. if w, ok := enc.Get().(WriteFlusher); ok {
  139. return w.Flush()
  140. }
  141. return nil
  142. }
  143. type WriteFlusher interface {
  144. Flush() error
  145. }
  146. func Str2Bytes(str string) []byte {
  147. // Copied from https://github.com/m3db/m3/blob/master/src/x/unsafe/string.go#L62
  148. if len(str) == 0 {
  149. return nil
  150. }
  151. // We need to declare a real byte slice so internally the compiler
  152. // knows to use an unsafe.Pointer to keep track of the underlying memory so that
  153. // once the slice's array pointer is updated with the pointer to the string's
  154. // underlying bytes, the compiler won't prematurely GC the memory when the string
  155. // goes out of scope.
  156. var b []byte
  157. byteHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
  158. // This makes sure that even if GC relocates the string's underlying
  159. // memory after this assignment, the corresponding unsafe.Pointer in the internal
  160. // slice struct will be updated accordingly to reflect the memory relocation.
  161. byteHeader.Data = (*reflect.StringHeader)(unsafe.Pointer(&str)).Data
  162. // It is important that we access str after we assign the Data
  163. // pointer of the string header to the Data pointer of the slice header to
  164. // make sure the string (and the underlying bytes backing the string) don't get
  165. // GC'ed before the assignment happens.
  166. l := len(str)
  167. byteHeader.Len = l
  168. byteHeader.Cap = l
  169. return b
  170. }