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.

205 lines
4.3 KiB

  1. package gen
  2. import (
  3. "io"
  4. "strconv"
  5. )
  6. func unmarshal(w io.Writer) *unmarshalGen {
  7. return &unmarshalGen{
  8. p: printer{w: w},
  9. }
  10. }
  11. type unmarshalGen struct {
  12. passes
  13. p printer
  14. hasfield bool
  15. }
  16. func (u *unmarshalGen) Method() Method { return Unmarshal }
  17. func (u *unmarshalGen) needsField() {
  18. if u.hasfield {
  19. return
  20. }
  21. u.p.print("\nvar field []byte; _ = field")
  22. u.hasfield = true
  23. }
  24. func (u *unmarshalGen) Execute(p Elem) error {
  25. u.hasfield = false
  26. if !u.p.ok() {
  27. return u.p.err
  28. }
  29. p = u.applyall(p)
  30. if p == nil {
  31. return nil
  32. }
  33. if !IsPrintable(p) {
  34. return nil
  35. }
  36. u.p.comment("UnmarshalMsg implements msgp.Unmarshaler")
  37. u.p.printf("\nfunc (%s %s) UnmarshalMsg(bts []byte) (o []byte, err error) {", p.Varname(), methodReceiver(p))
  38. next(u, p)
  39. u.p.print("\no = bts")
  40. u.p.nakedReturn()
  41. unsetReceiver(p)
  42. return u.p.err
  43. }
  44. // does assignment to the variable "name" with the type "base"
  45. func (u *unmarshalGen) assignAndCheck(name string, base string) {
  46. if !u.p.ok() {
  47. return
  48. }
  49. u.p.printf("\n%s, bts, err = msgp.Read%sBytes(bts)", name, base)
  50. u.p.print(errcheck)
  51. }
  52. func (u *unmarshalGen) gStruct(s *Struct) {
  53. if !u.p.ok() {
  54. return
  55. }
  56. if s.AsTuple {
  57. u.tuple(s)
  58. } else {
  59. u.mapstruct(s)
  60. }
  61. return
  62. }
  63. func (u *unmarshalGen) tuple(s *Struct) {
  64. // open block
  65. sz := randIdent()
  66. u.p.declare(sz, u32)
  67. u.assignAndCheck(sz, arrayHeader)
  68. u.p.arrayCheck(strconv.Itoa(len(s.Fields)), sz)
  69. for i := range s.Fields {
  70. if !u.p.ok() {
  71. return
  72. }
  73. next(u, s.Fields[i].FieldElem)
  74. }
  75. }
  76. func (u *unmarshalGen) mapstruct(s *Struct) {
  77. u.needsField()
  78. sz := randIdent()
  79. u.p.declare(sz, u32)
  80. u.assignAndCheck(sz, mapHeader)
  81. u.p.printf("\nfor %s > 0 {", sz)
  82. u.p.printf("\n%s--; field, bts, err = msgp.ReadMapKeyZC(bts)", sz)
  83. u.p.print(errcheck)
  84. u.p.print("\nswitch msgp.UnsafeString(field) {")
  85. for i := range s.Fields {
  86. if !u.p.ok() {
  87. return
  88. }
  89. u.p.printf("\ncase \"%s\":", s.Fields[i].FieldTag)
  90. next(u, s.Fields[i].FieldElem)
  91. }
  92. u.p.print("\ndefault:\nbts, err = msgp.Skip(bts)")
  93. u.p.print(errcheck)
  94. u.p.print("\n}\n}") // close switch and for loop
  95. }
  96. func (u *unmarshalGen) gBase(b *BaseElem) {
  97. if !u.p.ok() {
  98. return
  99. }
  100. refname := b.Varname() // assigned to
  101. lowered := b.Varname() // passed as argument
  102. if b.Convert {
  103. // begin 'tmp' block
  104. refname = randIdent()
  105. lowered = b.ToBase() + "(" + lowered + ")"
  106. u.p.printf("\n{\nvar %s %s", refname, b.BaseType())
  107. }
  108. switch b.Value {
  109. case Bytes:
  110. u.p.printf("\n%s, bts, err = msgp.ReadBytesBytes(bts, %s)", refname, lowered)
  111. case Ext:
  112. u.p.printf("\nbts, err = msgp.ReadExtensionBytes(bts, %s)", lowered)
  113. case IDENT:
  114. u.p.printf("\nbts, err = %s.UnmarshalMsg(bts)", lowered)
  115. default:
  116. u.p.printf("\n%s, bts, err = msgp.Read%sBytes(bts)", refname, b.BaseName())
  117. }
  118. u.p.print(errcheck)
  119. if b.Convert {
  120. // close 'tmp' block
  121. if b.ShimMode == Cast {
  122. u.p.printf("\n%s = %s(%s)\n", b.Varname(), b.FromBase(), refname)
  123. } else {
  124. u.p.printf("\n%s, err = %s(%s)", b.Varname(), b.FromBase(), refname)
  125. u.p.print(errcheck)
  126. }
  127. u.p.printf("}")
  128. }
  129. }
  130. func (u *unmarshalGen) gArray(a *Array) {
  131. if !u.p.ok() {
  132. return
  133. }
  134. // special case for [const]byte objects
  135. // see decode.go for symmetry
  136. if be, ok := a.Els.(*BaseElem); ok && be.Value == Byte {
  137. u.p.printf("\nbts, err = msgp.ReadExactBytes(bts, (%s)[:])", a.Varname())
  138. u.p.print(errcheck)
  139. return
  140. }
  141. sz := randIdent()
  142. u.p.declare(sz, u32)
  143. u.assignAndCheck(sz, arrayHeader)
  144. u.p.arrayCheck(coerceArraySize(a.Size), sz)
  145. u.p.rangeBlock(a.Index, a.Varname(), u, a.Els)
  146. }
  147. func (u *unmarshalGen) gSlice(s *Slice) {
  148. if !u.p.ok() {
  149. return
  150. }
  151. sz := randIdent()
  152. u.p.declare(sz, u32)
  153. u.assignAndCheck(sz, arrayHeader)
  154. u.p.resizeSlice(sz, s)
  155. u.p.rangeBlock(s.Index, s.Varname(), u, s.Els)
  156. }
  157. func (u *unmarshalGen) gMap(m *Map) {
  158. if !u.p.ok() {
  159. return
  160. }
  161. sz := randIdent()
  162. u.p.declare(sz, u32)
  163. u.assignAndCheck(sz, mapHeader)
  164. // allocate or clear map
  165. u.p.resizeMap(sz, m)
  166. // loop and get key,value
  167. u.p.printf("\nfor %s > 0 {", sz)
  168. u.p.printf("\nvar %s string; var %s %s; %s--", m.Keyidx, m.Validx, m.Value.TypeName(), sz)
  169. u.assignAndCheck(m.Keyidx, stringTyp)
  170. next(u, m.Value)
  171. u.p.mapAssign(m)
  172. u.p.closeblock()
  173. }
  174. func (u *unmarshalGen) gPtr(p *Ptr) {
  175. u.p.printf("\nif msgp.IsNil(bts) { bts, err = msgp.ReadNilBytes(bts); if err != nil { return }; %s = nil; } else { ", p.Varname())
  176. u.p.initPtr(p)
  177. next(u, p.Value)
  178. u.p.closeblock()
  179. }