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.

222 lines
4.3 KiB

  1. package gen
  2. import (
  3. "io"
  4. "strconv"
  5. )
  6. func decode(w io.Writer) *decodeGen {
  7. return &decodeGen{
  8. p: printer{w: w},
  9. hasfield: false,
  10. }
  11. }
  12. type decodeGen struct {
  13. passes
  14. p printer
  15. hasfield bool
  16. }
  17. func (d *decodeGen) Method() Method { return Decode }
  18. func (d *decodeGen) needsField() {
  19. if d.hasfield {
  20. return
  21. }
  22. d.p.print("\nvar field []byte; _ = field")
  23. d.hasfield = true
  24. }
  25. func (d *decodeGen) Execute(p Elem) error {
  26. p = d.applyall(p)
  27. if p == nil {
  28. return nil
  29. }
  30. d.hasfield = false
  31. if !d.p.ok() {
  32. return d.p.err
  33. }
  34. if !IsPrintable(p) {
  35. return nil
  36. }
  37. d.p.comment("DecodeMsg implements msgp.Decodable")
  38. d.p.printf("\nfunc (%s %s) DecodeMsg(dc *msgp.Reader) (err error) {", p.Varname(), methodReceiver(p))
  39. next(d, p)
  40. d.p.nakedReturn()
  41. unsetReceiver(p)
  42. return d.p.err
  43. }
  44. func (d *decodeGen) gStruct(s *Struct) {
  45. if !d.p.ok() {
  46. return
  47. }
  48. if s.AsTuple {
  49. d.structAsTuple(s)
  50. } else {
  51. d.structAsMap(s)
  52. }
  53. return
  54. }
  55. func (d *decodeGen) assignAndCheck(name string, typ string) {
  56. if !d.p.ok() {
  57. return
  58. }
  59. d.p.printf("\n%s, err = dc.Read%s()", name, typ)
  60. d.p.print(errcheck)
  61. }
  62. func (d *decodeGen) structAsTuple(s *Struct) {
  63. nfields := len(s.Fields)
  64. sz := randIdent()
  65. d.p.declare(sz, u32)
  66. d.assignAndCheck(sz, arrayHeader)
  67. d.p.arrayCheck(strconv.Itoa(nfields), sz)
  68. for i := range s.Fields {
  69. if !d.p.ok() {
  70. return
  71. }
  72. next(d, s.Fields[i].FieldElem)
  73. }
  74. }
  75. func (d *decodeGen) structAsMap(s *Struct) {
  76. d.needsField()
  77. sz := randIdent()
  78. d.p.declare(sz, u32)
  79. d.assignAndCheck(sz, mapHeader)
  80. d.p.printf("\nfor %s > 0 {\n%s--", sz, sz)
  81. d.assignAndCheck("field", mapKey)
  82. d.p.print("\nswitch msgp.UnsafeString(field) {")
  83. for i := range s.Fields {
  84. d.p.printf("\ncase \"%s\":", s.Fields[i].FieldTag)
  85. next(d, s.Fields[i].FieldElem)
  86. if !d.p.ok() {
  87. return
  88. }
  89. }
  90. d.p.print("\ndefault:\nerr = dc.Skip()")
  91. d.p.print(errcheck)
  92. d.p.closeblock() // close switch
  93. d.p.closeblock() // close for loop
  94. }
  95. func (d *decodeGen) gBase(b *BaseElem) {
  96. if !d.p.ok() {
  97. return
  98. }
  99. // open block for 'tmp'
  100. var tmp string
  101. if b.Convert {
  102. tmp = randIdent()
  103. d.p.printf("\n{ var %s %s", tmp, b.BaseType())
  104. }
  105. vname := b.Varname() // e.g. "z.FieldOne"
  106. bname := b.BaseName() // e.g. "Float64"
  107. // handle special cases
  108. // for object type.
  109. switch b.Value {
  110. case Bytes:
  111. if b.Convert {
  112. d.p.printf("\n%s, err = dc.ReadBytes([]byte(%s))", tmp, vname)
  113. } else {
  114. d.p.printf("\n%s, err = dc.ReadBytes(%s)", vname, vname)
  115. }
  116. case IDENT:
  117. d.p.printf("\nerr = %s.DecodeMsg(dc)", vname)
  118. case Ext:
  119. d.p.printf("\nerr = dc.ReadExtension(%s)", vname)
  120. default:
  121. if b.Convert {
  122. d.p.printf("\n%s, err = dc.Read%s()", tmp, bname)
  123. } else {
  124. d.p.printf("\n%s, err = dc.Read%s()", vname, bname)
  125. }
  126. }
  127. d.p.print(errcheck)
  128. // close block for 'tmp'
  129. if b.Convert {
  130. if b.ShimMode == Cast {
  131. d.p.printf("\n%s = %s(%s)\n}", vname, b.FromBase(), tmp)
  132. } else {
  133. d.p.printf("\n%s, err = %s(%s)\n}", vname, b.FromBase(), tmp)
  134. d.p.print(errcheck)
  135. }
  136. }
  137. }
  138. func (d *decodeGen) gMap(m *Map) {
  139. if !d.p.ok() {
  140. return
  141. }
  142. sz := randIdent()
  143. // resize or allocate map
  144. d.p.declare(sz, u32)
  145. d.assignAndCheck(sz, mapHeader)
  146. d.p.resizeMap(sz, m)
  147. // for element in map, read string/value
  148. // pair and assign
  149. d.p.printf("\nfor %s > 0 {\n%s--", sz, sz)
  150. d.p.declare(m.Keyidx, "string")
  151. d.p.declare(m.Validx, m.Value.TypeName())
  152. d.assignAndCheck(m.Keyidx, stringTyp)
  153. next(d, m.Value)
  154. d.p.mapAssign(m)
  155. d.p.closeblock()
  156. }
  157. func (d *decodeGen) gSlice(s *Slice) {
  158. if !d.p.ok() {
  159. return
  160. }
  161. sz := randIdent()
  162. d.p.declare(sz, u32)
  163. d.assignAndCheck(sz, arrayHeader)
  164. d.p.resizeSlice(sz, s)
  165. d.p.rangeBlock(s.Index, s.Varname(), d, s.Els)
  166. }
  167. func (d *decodeGen) gArray(a *Array) {
  168. if !d.p.ok() {
  169. return
  170. }
  171. // special case if we have [const]byte
  172. if be, ok := a.Els.(*BaseElem); ok && (be.Value == Byte || be.Value == Uint8) {
  173. d.p.printf("\nerr = dc.ReadExactBytes((%s)[:])", a.Varname())
  174. d.p.print(errcheck)
  175. return
  176. }
  177. sz := randIdent()
  178. d.p.declare(sz, u32)
  179. d.assignAndCheck(sz, arrayHeader)
  180. d.p.arrayCheck(coerceArraySize(a.Size), sz)
  181. d.p.rangeBlock(a.Index, a.Varname(), d, a.Els)
  182. }
  183. func (d *decodeGen) gPtr(p *Ptr) {
  184. if !d.p.ok() {
  185. return
  186. }
  187. d.p.print("\nif dc.IsNil() {")
  188. d.p.print("\nerr = dc.ReadNil()")
  189. d.p.print(errcheck)
  190. d.p.printf("\n%s = nil\n} else {", p.Varname())
  191. d.p.initPtr(p)
  192. next(d, p.Value)
  193. d.p.closeblock()
  194. }