real_encoder.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package sarama
  2. import (
  3. "encoding/binary"
  4. "github.com/rcrowley/go-metrics"
  5. )
  6. type realEncoder struct {
  7. raw []byte
  8. off int
  9. stack []pushEncoder
  10. registry metrics.Registry
  11. }
  12. // primitives
  13. func (re *realEncoder) putInt8(in int8) {
  14. re.raw[re.off] = byte(in)
  15. re.off++
  16. }
  17. func (re *realEncoder) putInt16(in int16) {
  18. binary.BigEndian.PutUint16(re.raw[re.off:], uint16(in))
  19. re.off += 2
  20. }
  21. func (re *realEncoder) putInt32(in int32) {
  22. binary.BigEndian.PutUint32(re.raw[re.off:], uint32(in))
  23. re.off += 4
  24. }
  25. func (re *realEncoder) putInt64(in int64) {
  26. binary.BigEndian.PutUint64(re.raw[re.off:], uint64(in))
  27. re.off += 8
  28. }
  29. func (re *realEncoder) putVarint(in int64) {
  30. re.off += binary.PutVarint(re.raw[re.off:], in)
  31. }
  32. func (re *realEncoder) putArrayLength(in int) error {
  33. re.putInt32(int32(in))
  34. return nil
  35. }
  36. func (re *realEncoder) putBool(in bool) {
  37. if in {
  38. re.putInt8(1)
  39. return
  40. }
  41. re.putInt8(0)
  42. }
  43. // collection
  44. func (re *realEncoder) putRawBytes(in []byte) error {
  45. copy(re.raw[re.off:], in)
  46. re.off += len(in)
  47. return nil
  48. }
  49. func (re *realEncoder) putBytes(in []byte) error {
  50. if in == nil {
  51. re.putInt32(-1)
  52. return nil
  53. }
  54. re.putInt32(int32(len(in)))
  55. return re.putRawBytes(in)
  56. }
  57. func (re *realEncoder) putVarintBytes(in []byte) error {
  58. if in == nil {
  59. re.putVarint(-1)
  60. return nil
  61. }
  62. re.putVarint(int64(len(in)))
  63. return re.putRawBytes(in)
  64. }
  65. func (re *realEncoder) putString(in string) error {
  66. re.putInt16(int16(len(in)))
  67. copy(re.raw[re.off:], in)
  68. re.off += len(in)
  69. return nil
  70. }
  71. func (re *realEncoder) putNullableString(in *string) error {
  72. if in == nil {
  73. re.putInt16(-1)
  74. return nil
  75. }
  76. return re.putString(*in)
  77. }
  78. func (re *realEncoder) putStringArray(in []string) error {
  79. err := re.putArrayLength(len(in))
  80. if err != nil {
  81. return err
  82. }
  83. for _, val := range in {
  84. if err := re.putString(val); err != nil {
  85. return err
  86. }
  87. }
  88. return nil
  89. }
  90. func (re *realEncoder) putInt32Array(in []int32) error {
  91. err := re.putArrayLength(len(in))
  92. if err != nil {
  93. return err
  94. }
  95. for _, val := range in {
  96. re.putInt32(val)
  97. }
  98. return nil
  99. }
  100. func (re *realEncoder) putInt64Array(in []int64) error {
  101. err := re.putArrayLength(len(in))
  102. if err != nil {
  103. return err
  104. }
  105. for _, val := range in {
  106. re.putInt64(val)
  107. }
  108. return nil
  109. }
  110. func (re *realEncoder) offset() int {
  111. return re.off
  112. }
  113. // stacks
  114. func (re *realEncoder) push(in pushEncoder) {
  115. in.saveOffset(re.off)
  116. re.off += in.reserveLength()
  117. re.stack = append(re.stack, in)
  118. }
  119. func (re *realEncoder) pop() error {
  120. // this is go's ugly pop pattern (the inverse of append)
  121. in := re.stack[len(re.stack)-1]
  122. re.stack = re.stack[:len(re.stack)-1]
  123. return in.run(re.off, re.raw)
  124. }
  125. // we do record metrics during the real encoder pass
  126. func (re *realEncoder) metricRegistry() metrics.Registry {
  127. return re.registry
  128. }