github.com/chrislusf/greenpack@v3.7.1-0.20170911073826-ad5bd10b7c47+incompatible/gen/decode.go (about) 1 package gen 2 3 import ( 4 "fmt" 5 "io" 6 "strconv" 7 "strings" 8 9 "github.com/glycerine/greenpack/cfg" 10 ) 11 12 func decode(w io.Writer, cfg *cfg.GreenConfig) *decodeGen { 13 return &decodeGen{ 14 p: printer{w: w}, 15 hasfield: false, 16 cfg: cfg, 17 } 18 } 19 20 type decodeGen struct { 21 passes 22 p printer 23 hasfield bool 24 depth int 25 cfg *cfg.GreenConfig 26 lifo []bool 27 28 post postDefs 29 } 30 31 func (s *decodeGen) MethodPrefix() string { 32 return s.cfg.MethodPrefix 33 } 34 35 type postDefs struct { 36 varnames map[string]int 37 endlines []string // var declarations declared after method defitions. 38 } 39 40 func (d *postDefs) add(key string, format string, args ...interface{}) { 41 if len(d.varnames) == 0 { 42 d.varnames = make(map[string]int) 43 d.varnames[key] = 0 44 } else { 45 _, already := d.varnames[key] 46 if already { 47 return 48 } 49 } 50 d.endlines = append(d.endlines, fmt.Sprintf(format, args...)) 51 } 52 53 func (d *postDefs) reset() { 54 d.varnames = nil 55 d.endlines = d.endlines[:0] 56 } 57 58 func (d *decodeGen) postLines() { 59 lines := strings.Join(d.post.endlines, "\n") 60 d.p.printf("\n%s\n", lines) 61 d.post.reset() 62 } 63 64 func (d *decodeGen) Method() Method { return Decode } 65 66 func (d *decodeGen) needsField() { 67 if d.hasfield { 68 return 69 } 70 d.p.print("\nvar field []byte; _ = field") 71 d.hasfield = true 72 } 73 74 func (d *decodeGen) Execute(p Elem) error { 75 p = d.applyall(p) 76 if p == nil { 77 return nil 78 } 79 d.hasfield = false 80 if !d.p.ok() { 81 return d.p.err 82 } 83 84 if !IsPrintable(p) { 85 return nil 86 } 87 88 d.p.comment(fmt.Sprintf("%sDecodeMsg implements msgp.Decodable", d.cfg.MethodPrefix)) 89 d.p.comment("We treat empty fields as if we read a Nil from the wire.") 90 d.p.printf("\nfunc (%s %s) %sDecodeMsg(dc *msgp.Reader) (err error) {\n", p.Varname(), methodReceiver(p), d.cfg.MethodPrefix) 91 92 if !d.cfg.AllTuple { 93 d.p.printf(`var sawTopNil bool 94 if dc.IsNil() { 95 sawTopNil = true 96 err = dc.ReadNil() 97 if err != nil { 98 return 99 } 100 dc.PushAlwaysNil() 101 } 102 `) 103 } 104 105 // next will increment k, but we want the first, top level DecodeMsg 106 // to refer to this same k ... 107 next(d, p) 108 109 if !d.cfg.AllTuple { 110 111 d.p.printf(` 112 if sawTopNil { 113 dc.PopAlwaysNil() 114 } 115 `) 116 } 117 118 d.p.postLoadHook() 119 d.p.nakedReturn() 120 unsetReceiver(p) 121 d.postLines() 122 return d.p.err 123 } 124 125 func (d *decodeGen) gStruct(s *Struct) { 126 d.depth++ 127 defer func() { 128 d.depth-- 129 }() 130 131 if !d.p.ok() { 132 return 133 } 134 if d.cfg.AllTuple || s.AsTuple { 135 d.structAsTuple(s) 136 } else { 137 d.structAsMap(s) 138 } 139 return 140 } 141 142 func (d *decodeGen) assignAndCheck(name string, typ string) { 143 if !d.p.ok() { 144 return 145 } 146 d.p.printf("\n%s, err = dc.Read%s()", name, typ) 147 d.p.print(errcheck) 148 } 149 150 func (d *decodeGen) structAsTuple(s *Struct) { 151 nfields := len(s.Fields) - s.SkipCount 152 153 sz := gensym() 154 d.p.declare(sz, u32) 155 d.assignAndCheck(sz, arrayHeader) 156 d.p.arrayCheck(strconv.Itoa(nfields), sz, "") 157 for i := range s.Fields { 158 if s.Fields[i].Skip { 159 continue 160 } 161 if !d.p.ok() { 162 return 163 } 164 next(d, s.Fields[i].FieldElem) 165 } 166 } 167 168 /* func (d *decodeGen) structAsMap(s *Struct): 169 // 170 // Missing (empty) field handling logic: 171 // 172 // The approach to missing field handling is to 173 // keep the logic the same whether the field is 174 // missing or nil on the wire. To do so we use 175 // the Reader.PushAlwaysNil() method to tell 176 // the Reader to pretend to supply 177 // only nils until further notice. The further 178 // notice comes from the terminating dc.PopAlwaysNil() 179 // calls emptying the LIFO. The stack is 180 // needed because multiple struct decodes may 181 // be nested due to inlining. 182 */ 183 func (d *decodeGen) structAsMap(s *Struct) { 184 n := len(s.Fields) // - s.SkipCount 185 //fmt.Printf("\n in structAsMap!... n = %v. SkipCount=%v\n", n, s.SkipCount) 186 if n == 0 { 187 return 188 } 189 d.needsField() 190 191 k := genSerial() 192 skipclue := d.cfg.SkipZidClue || d.cfg.Msgpack2 193 194 tmpl, nStr := genDecodeMsgTemplate(k) 195 196 fieldOrder := fmt.Sprintf("\n var decodeMsgFieldOrder%s = []string{", nStr) 197 fieldSkip := fmt.Sprintf("\n var decodeMsgFieldSkip%s = []bool{", nStr) 198 for i := range s.Fields { 199 if s.Fields[i].Skip { 200 fieldSkip += fmt.Sprintf("true,") 201 } else { 202 fieldSkip += fmt.Sprintf("false,") 203 } 204 fld := s.Fields[i].FieldTagZidClue 205 if skipclue { 206 fld = s.Fields[i].FieldTag 207 } 208 fieldOrder += fmt.Sprintf("%q,", fld) 209 } 210 fieldOrder += "}\n" 211 fieldSkip += "}\n" 212 varname := strings.Replace(s.TypeName(), "\n", ";", -1) 213 d.post.add(varname, "\n// fields of %s%s%s", 214 varname, fieldOrder, fieldSkip) 215 216 //fmt.Printf("\n printing maxField%s to be %v\n", nStr, n) 217 d.p.printf("\n const maxFields%s = %d\n", nStr, n) 218 219 found := "found" + nStr 220 d.p.printf(tmpl) 221 // after printing tmpl, we are at this point: 222 // switch curField_ { 223 // -- templateDecodeMsg ends here -- 224 225 for i := range s.Fields { 226 if s.Fields[i].Skip { 227 continue 228 } 229 fld := s.Fields[i].FieldTagZidClue 230 if skipclue { 231 fld = s.Fields[i].FieldTag 232 } 233 234 d.p.printf("\ncase \"%s\":", fld) 235 d.p.printf("\n%s[%d]=true;", found, i) 236 //d.p.printf("\n fmt.Printf(\"I found field '%s' at depth=%d. dc.AlwaysNil = %%v\", dc.AlwaysNil);\n", fld, d.depth) 237 d.depth++ 238 next(d, s.Fields[i].FieldElem) 239 d.depth-- 240 if !d.p.ok() { 241 return 242 } 243 } 244 d.p.print("\ndefault:\nerr = dc.Skip()") 245 d.p.print(errcheck) 246 d.p.closeblock() // close switch 247 d.p.closeblock() // close for loop 248 249 d.p.printf("\n if nextMiss%s != -1 {dc.PopAlwaysNil(); }\n", nStr) 250 } 251 252 func (d *decodeGen) gBase(b *BaseElem) { 253 if !d.p.ok() { 254 return 255 } 256 257 // open block for 'tmp' 258 var tmp string 259 if b.Convert { 260 tmp = gensym() 261 d.p.printf("\n{ var %s %s", tmp, b.BaseType()) 262 } 263 264 vname := b.Varname() // e.g. "z.FieldOne" 265 bname := b.BaseName() // e.g. "Float64" 266 267 // handle special cases 268 // for object type. 269 switch b.Value { 270 case Bytes: 271 if b.Convert { 272 d.p.printf("\n%s, err = dc.ReadBytes([]byte(%s))", tmp, vname) 273 } else { 274 d.p.printf("\n%s, err = dc.ReadBytes(%s)", vname, vname) 275 } 276 case IDENT: 277 d.p.printf("\nerr = %s.%sDecodeMsg(dc)", vname, d.cfg.MethodPrefix) 278 case Ext: 279 d.p.printf("\n if !dc.IsNil() {") 280 d.p.printf("\nerr = dc.ReadExtension(%s)\n} else { err = dc.ReadNil() }\n", vname) 281 default: 282 if b.Convert { 283 d.p.printf("\n%s, err = dc.Read%s()", tmp, bname) 284 } else { 285 d.p.printf("\n%s, err = dc.Read%s()", vname, bname) 286 } 287 } 288 289 // close block for 'tmp' 290 if b.Convert { 291 d.p.printf("\n%s = %s(%s)\n}", vname, b.FromBase(), tmp) 292 } 293 294 d.p.print(errcheck) 295 } 296 297 func (d *decodeGen) gMap(m *Map) { 298 d.depth++ 299 defer func() { 300 d.depth-- 301 }() 302 303 if !d.p.ok() { 304 return 305 } 306 sz := gensym() 307 308 // resize or allocate map 309 d.p.declare(sz, u32) 310 d.assignAndCheck(sz, mapHeader) 311 d.p.resizeMap(sz, m) 312 313 // for element in map, read string/value 314 // pair and assign 315 d.p.printf("\nfor %s > 0 {\n%s--", sz, sz) 316 d.p.declare(m.Keyidx, m.KeyDeclTyp) 317 d.p.declare(m.Validx, m.Value.TypeName()) 318 d.assignAndCheck(m.Keyidx, m.KeyTyp) 319 next(d, m.Value) 320 d.p.mapAssign(m) 321 d.p.closeblock() 322 } 323 324 func (d *decodeGen) gSlice(s *Slice) { 325 if !d.p.ok() { 326 return 327 } 328 sz := gensym() 329 d.p.declare(sz, u32) 330 d.assignAndCheck(sz, arrayHeader) 331 d.p.resizeSlice(sz, s) 332 d.p.rangeBlock(s.Index, s.Varname(), d, s.Els) 333 } 334 335 func (d *decodeGen) gArray(a *Array) { 336 if !d.p.ok() { 337 return 338 } 339 d.p.printf(` 340 if dc.AlwaysNil { 341 // nothing more here 342 } else if dc.IsNil() { 343 err = dc.ReadNil() 344 if err != nil { 345 return 346 } 347 }`) // possible else next 348 349 // special case if we have [const]byte 350 if be, ok := a.Els.(*BaseElem); ok && (be.Value == Byte || be.Value == Uint8) { 351 d.p.printf("\nerr = dc.ReadExactBytes(%s[:])", a.Varname()) 352 d.p.print(errcheck) 353 return 354 } else { 355 d.p.printf(" else {\n") 356 } 357 sz := gensym() 358 d.p.declare(sz, u32) 359 d.assignAndCheck(sz, arrayHeader) 360 d.p.arrayCheck(a.SizeResolved, sz, "!dc.IsNil() && ") 361 d.p.closeblock() 362 d.p.rangeBlock(a.Index, a.Varname(), d, a.Els) 363 } 364 365 func (d *decodeGen) gPtr(p *Ptr) { 366 if !d.p.ok() { 367 return 368 } 369 370 d.p.printf(` 371 if dc.IsNil() { 372 err = dc.ReadNil() 373 if err != nil { 374 return 375 } 376 `) 377 378 vname := p.Varname() 379 base, isBase := p.Value.(*BaseElem) 380 if isBase { 381 //d.p.printf("\n // we have a BaseElem: %#v \n", base) 382 switch base.Value { 383 case IDENT: 384 //d.p.printf("\n // we have an IDENT: \n") 385 d.p.printf( 386 ` 387 if %s != nil { 388 dc.PushAlwaysNil() 389 err = %s.%sDecodeMsg(dc) 390 if err != nil { 391 return 392 } 393 dc.PopAlwaysNil() 394 } 395 } else { 396 // not Nil, we have something to read 397 `, vname, vname, d.cfg.MethodPrefix) 398 case Ext: 399 d.p.printf("\n // we have an base.Value of Ext: replace the Ext iff already allocated") 400 d.p.printf("\nif %s != nil {\n %s = new(msgp.RawExtension) } \n"+ 401 " } else {\n // we have bytes in dc to read\n", vname, vname) 402 default: 403 //d.p.printf("\n // we have an unknown base.Value type= %T/val=%#v: \n", base.Value, base.Value) 404 d.p.printf("\n } else { \n") 405 } 406 } else { 407 // !isBase 408 d.p.printf("\n%s = nil\n} else {", vname) 409 } 410 d.p.initPtr(p) 411 next(d, p.Value) 412 d.p.closeblock() 413 }