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.

198 lines
3.8 KiB

  1. package gen
  2. import (
  3. "fmt"
  4. "io"
  5. "github.com/tinylib/msgp/msgp"
  6. )
  7. func encode(w io.Writer) *encodeGen {
  8. return &encodeGen{
  9. p: printer{w: w},
  10. }
  11. }
  12. type encodeGen struct {
  13. passes
  14. p printer
  15. fuse []byte
  16. }
  17. func (e *encodeGen) Method() Method { return Encode }
  18. func (e *encodeGen) Apply(dirs []string) error {
  19. return nil
  20. }
  21. func (e *encodeGen) writeAndCheck(typ string, argfmt string, arg interface{}) {
  22. e.p.printf("\nerr = en.Write%s(%s)", typ, fmt.Sprintf(argfmt, arg))
  23. e.p.print(errcheck)
  24. }
  25. func (e *encodeGen) fuseHook() {
  26. if len(e.fuse) > 0 {
  27. e.appendraw(e.fuse)
  28. e.fuse = e.fuse[:0]
  29. }
  30. }
  31. func (e *encodeGen) Fuse(b []byte) {
  32. if len(e.fuse) > 0 {
  33. e.fuse = append(e.fuse, b...)
  34. } else {
  35. e.fuse = b
  36. }
  37. }
  38. func (e *encodeGen) Execute(p Elem) error {
  39. if !e.p.ok() {
  40. return e.p.err
  41. }
  42. p = e.applyall(p)
  43. if p == nil {
  44. return nil
  45. }
  46. if !IsPrintable(p) {
  47. return nil
  48. }
  49. e.p.comment("EncodeMsg implements msgp.Encodable")
  50. e.p.printf("\nfunc (%s %s) EncodeMsg(en *msgp.Writer) (err error) {", p.Varname(), imutMethodReceiver(p))
  51. next(e, p)
  52. e.p.nakedReturn()
  53. return e.p.err
  54. }
  55. func (e *encodeGen) gStruct(s *Struct) {
  56. if !e.p.ok() {
  57. return
  58. }
  59. if s.AsTuple {
  60. e.tuple(s)
  61. } else {
  62. e.structmap(s)
  63. }
  64. return
  65. }
  66. func (e *encodeGen) tuple(s *Struct) {
  67. nfields := len(s.Fields)
  68. data := msgp.AppendArrayHeader(nil, uint32(nfields))
  69. e.p.printf("\n// array header, size %d", nfields)
  70. e.Fuse(data)
  71. if len(s.Fields) == 0 {
  72. e.fuseHook()
  73. }
  74. for i := range s.Fields {
  75. if !e.p.ok() {
  76. return
  77. }
  78. next(e, s.Fields[i].FieldElem)
  79. }
  80. }
  81. func (e *encodeGen) appendraw(bts []byte) {
  82. e.p.print("\nerr = en.Append(")
  83. for i, b := range bts {
  84. if i != 0 {
  85. e.p.print(", ")
  86. }
  87. e.p.printf("0x%x", b)
  88. }
  89. e.p.print(")\nif err != nil { return }")
  90. }
  91. func (e *encodeGen) structmap(s *Struct) {
  92. nfields := len(s.Fields)
  93. data := msgp.AppendMapHeader(nil, uint32(nfields))
  94. e.p.printf("\n// map header, size %d", nfields)
  95. e.Fuse(data)
  96. if len(s.Fields) == 0 {
  97. e.fuseHook()
  98. }
  99. for i := range s.Fields {
  100. if !e.p.ok() {
  101. return
  102. }
  103. data = msgp.AppendString(nil, s.Fields[i].FieldTag)
  104. e.p.printf("\n// write %q", s.Fields[i].FieldTag)
  105. e.Fuse(data)
  106. next(e, s.Fields[i].FieldElem)
  107. }
  108. }
  109. func (e *encodeGen) gMap(m *Map) {
  110. if !e.p.ok() {
  111. return
  112. }
  113. e.fuseHook()
  114. vname := m.Varname()
  115. e.writeAndCheck(mapHeader, lenAsUint32, vname)
  116. e.p.printf("\nfor %s, %s := range %s {", m.Keyidx, m.Validx, vname)
  117. e.writeAndCheck(stringTyp, literalFmt, m.Keyidx)
  118. next(e, m.Value)
  119. e.p.closeblock()
  120. }
  121. func (e *encodeGen) gPtr(s *Ptr) {
  122. if !e.p.ok() {
  123. return
  124. }
  125. e.fuseHook()
  126. e.p.printf("\nif %s == nil { err = en.WriteNil(); if err != nil { return; } } else {", s.Varname())
  127. next(e, s.Value)
  128. e.p.closeblock()
  129. }
  130. func (e *encodeGen) gSlice(s *Slice) {
  131. if !e.p.ok() {
  132. return
  133. }
  134. e.fuseHook()
  135. e.writeAndCheck(arrayHeader, lenAsUint32, s.Varname())
  136. e.p.rangeBlock(s.Index, s.Varname(), e, s.Els)
  137. }
  138. func (e *encodeGen) gArray(a *Array) {
  139. if !e.p.ok() {
  140. return
  141. }
  142. e.fuseHook()
  143. // shortcut for [const]byte
  144. if be, ok := a.Els.(*BaseElem); ok && (be.Value == Byte || be.Value == Uint8) {
  145. e.p.printf("\nerr = en.WriteBytes((%s)[:])", a.Varname())
  146. e.p.print(errcheck)
  147. return
  148. }
  149. e.writeAndCheck(arrayHeader, literalFmt, coerceArraySize(a.Size))
  150. e.p.rangeBlock(a.Index, a.Varname(), e, a.Els)
  151. }
  152. func (e *encodeGen) gBase(b *BaseElem) {
  153. if !e.p.ok() {
  154. return
  155. }
  156. e.fuseHook()
  157. vname := b.Varname()
  158. if b.Convert {
  159. if b.ShimMode == Cast {
  160. vname = tobaseConvert(b)
  161. } else {
  162. vname = randIdent()
  163. e.p.printf("\nvar %s %s", vname, b.BaseType())
  164. e.p.printf("\n%s, err = %s", vname, tobaseConvert(b))
  165. e.p.printf(errcheck)
  166. }
  167. }
  168. if b.Value == IDENT { // unknown identity
  169. e.p.printf("\nerr = %s.EncodeMsg(en)", vname)
  170. e.p.print(errcheck)
  171. } else { // typical case
  172. e.writeAndCheck(b.BaseName(), literalFmt, vname)
  173. }
  174. }