github.com/theQRL/go-zond@v0.1.1/rlp/rlpgen/gen.go (about) 1 // Copyright 2022 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bytes" 21 "fmt" 22 "go/format" 23 "go/types" 24 "sort" 25 26 "github.com/theQRL/go-zond/rlp/internal/rlpstruct" 27 ) 28 29 // buildContext keeps the data needed for make*Op. 30 type buildContext struct { 31 topType *types.Named // the type we're creating methods for 32 33 encoderIface *types.Interface 34 decoderIface *types.Interface 35 rawValueType *types.Named 36 37 typeToStructCache map[types.Type]*rlpstruct.Type 38 } 39 40 func newBuildContext(packageRLP *types.Package) *buildContext { 41 enc := packageRLP.Scope().Lookup("Encoder").Type().Underlying() 42 dec := packageRLP.Scope().Lookup("Decoder").Type().Underlying() 43 rawv := packageRLP.Scope().Lookup("RawValue").Type() 44 return &buildContext{ 45 typeToStructCache: make(map[types.Type]*rlpstruct.Type), 46 encoderIface: enc.(*types.Interface), 47 decoderIface: dec.(*types.Interface), 48 rawValueType: rawv.(*types.Named), 49 } 50 } 51 52 func (bctx *buildContext) isEncoder(typ types.Type) bool { 53 return types.Implements(typ, bctx.encoderIface) 54 } 55 56 func (bctx *buildContext) isDecoder(typ types.Type) bool { 57 return types.Implements(typ, bctx.decoderIface) 58 } 59 60 // typeToStructType converts typ to rlpstruct.Type. 61 func (bctx *buildContext) typeToStructType(typ types.Type) *rlpstruct.Type { 62 if prev := bctx.typeToStructCache[typ]; prev != nil { 63 return prev // short-circuit for recursive types. 64 } 65 66 // Resolve named types to their underlying type, but keep the name. 67 name := types.TypeString(typ, nil) 68 for { 69 utype := typ.Underlying() 70 if utype == typ { 71 break 72 } 73 typ = utype 74 } 75 76 // Create the type and store it in cache. 77 t := &rlpstruct.Type{ 78 Name: name, 79 Kind: typeReflectKind(typ), 80 IsEncoder: bctx.isEncoder(typ), 81 IsDecoder: bctx.isDecoder(typ), 82 } 83 bctx.typeToStructCache[typ] = t 84 85 // Assign element type. 86 switch typ.(type) { 87 case *types.Array, *types.Slice, *types.Pointer: 88 etype := typ.(interface{ Elem() types.Type }).Elem() 89 t.Elem = bctx.typeToStructType(etype) 90 } 91 return t 92 } 93 94 // genContext is passed to the gen* methods of op when generating 95 // the output code. It tracks packages to be imported by the output 96 // file and assigns unique names of temporary variables. 97 type genContext struct { 98 inPackage *types.Package 99 imports map[string]struct{} 100 tempCounter int 101 } 102 103 func newGenContext(inPackage *types.Package) *genContext { 104 return &genContext{ 105 inPackage: inPackage, 106 imports: make(map[string]struct{}), 107 } 108 } 109 110 func (ctx *genContext) temp() string { 111 v := fmt.Sprintf("_tmp%d", ctx.tempCounter) 112 ctx.tempCounter++ 113 return v 114 } 115 116 func (ctx *genContext) resetTemp() { 117 ctx.tempCounter = 0 118 } 119 120 func (ctx *genContext) addImport(path string) { 121 if path == ctx.inPackage.Path() { 122 return // avoid importing the package that we're generating in. 123 } 124 // TODO: renaming? 125 ctx.imports[path] = struct{}{} 126 } 127 128 // importsList returns all packages that need to be imported. 129 func (ctx *genContext) importsList() []string { 130 imp := make([]string, 0, len(ctx.imports)) 131 for k := range ctx.imports { 132 imp = append(imp, k) 133 } 134 sort.Strings(imp) 135 return imp 136 } 137 138 // qualify is the types.Qualifier used for printing types. 139 func (ctx *genContext) qualify(pkg *types.Package) string { 140 if pkg.Path() == ctx.inPackage.Path() { 141 return "" 142 } 143 ctx.addImport(pkg.Path()) 144 // TODO: renaming? 145 return pkg.Name() 146 } 147 148 type op interface { 149 // genWrite creates the encoder. The generated code should write v, 150 // which is any Go expression, to the rlp.EncoderBuffer 'w'. 151 genWrite(ctx *genContext, v string) string 152 153 // genDecode creates the decoder. The generated code should read 154 // a value from the rlp.Stream 'dec' and store it to dst. 155 genDecode(ctx *genContext) (string, string) 156 } 157 158 // basicOp handles basic types bool, uint*, string. 159 type basicOp struct { 160 typ types.Type 161 writeMethod string // calle write the value 162 writeArgType types.Type // parameter type of writeMethod 163 decMethod string 164 decResultType types.Type // return type of decMethod 165 decUseBitSize bool // if true, result bit size is appended to decMethod 166 } 167 168 func (*buildContext) makeBasicOp(typ *types.Basic) (op, error) { 169 op := basicOp{typ: typ} 170 kind := typ.Kind() 171 switch { 172 case kind == types.Bool: 173 op.writeMethod = "WriteBool" 174 op.writeArgType = types.Typ[types.Bool] 175 op.decMethod = "Bool" 176 op.decResultType = types.Typ[types.Bool] 177 case kind >= types.Uint8 && kind <= types.Uint64: 178 op.writeMethod = "WriteUint64" 179 op.writeArgType = types.Typ[types.Uint64] 180 op.decMethod = "Uint" 181 op.decResultType = typ 182 op.decUseBitSize = true 183 case kind == types.String: 184 op.writeMethod = "WriteString" 185 op.writeArgType = types.Typ[types.String] 186 op.decMethod = "String" 187 op.decResultType = types.Typ[types.String] 188 default: 189 return nil, fmt.Errorf("unhandled basic type: %v", typ) 190 } 191 return op, nil 192 } 193 194 func (*buildContext) makeByteSliceOp(typ *types.Slice) op { 195 if !isByte(typ.Elem()) { 196 panic("non-byte slice type in makeByteSliceOp") 197 } 198 bslice := types.NewSlice(types.Typ[types.Uint8]) 199 return basicOp{ 200 typ: typ, 201 writeMethod: "WriteBytes", 202 writeArgType: bslice, 203 decMethod: "Bytes", 204 decResultType: bslice, 205 } 206 } 207 208 func (bctx *buildContext) makeRawValueOp() op { 209 bslice := types.NewSlice(types.Typ[types.Uint8]) 210 return basicOp{ 211 typ: bctx.rawValueType, 212 writeMethod: "Write", 213 writeArgType: bslice, 214 decMethod: "Raw", 215 decResultType: bslice, 216 } 217 } 218 219 func (op basicOp) writeNeedsConversion() bool { 220 return !types.AssignableTo(op.typ, op.writeArgType) 221 } 222 223 func (op basicOp) decodeNeedsConversion() bool { 224 return !types.AssignableTo(op.decResultType, op.typ) 225 } 226 227 func (op basicOp) genWrite(ctx *genContext, v string) string { 228 if op.writeNeedsConversion() { 229 v = fmt.Sprintf("%s(%s)", op.writeArgType, v) 230 } 231 return fmt.Sprintf("w.%s(%s)\n", op.writeMethod, v) 232 } 233 234 func (op basicOp) genDecode(ctx *genContext) (string, string) { 235 var ( 236 resultV = ctx.temp() 237 result = resultV 238 method = op.decMethod 239 ) 240 if op.decUseBitSize { 241 // Note: For now, this only works for platform-independent integer 242 // sizes. makeBasicOp forbids the platform-dependent types. 243 var sizes types.StdSizes 244 method = fmt.Sprintf("%s%d", op.decMethod, sizes.Sizeof(op.typ)*8) 245 } 246 247 // Call the decoder method. 248 var b bytes.Buffer 249 fmt.Fprintf(&b, "%s, err := dec.%s()\n", resultV, method) 250 fmt.Fprintf(&b, "if err != nil { return err }\n") 251 if op.decodeNeedsConversion() { 252 conv := ctx.temp() 253 fmt.Fprintf(&b, "%s := %s(%s)\n", conv, types.TypeString(op.typ, ctx.qualify), resultV) 254 result = conv 255 } 256 return result, b.String() 257 } 258 259 // byteArrayOp handles [...]byte. 260 type byteArrayOp struct { 261 typ types.Type 262 name types.Type // name != typ for named byte array types (e.g. common.Address) 263 } 264 265 func (bctx *buildContext) makeByteArrayOp(name *types.Named, typ *types.Array) byteArrayOp { 266 nt := types.Type(name) 267 if name == nil { 268 nt = typ 269 } 270 return byteArrayOp{typ, nt} 271 } 272 273 func (op byteArrayOp) genWrite(ctx *genContext, v string) string { 274 return fmt.Sprintf("w.WriteBytes(%s[:])\n", v) 275 } 276 277 func (op byteArrayOp) genDecode(ctx *genContext) (string, string) { 278 var resultV = ctx.temp() 279 280 var b bytes.Buffer 281 fmt.Fprintf(&b, "var %s %s\n", resultV, types.TypeString(op.name, ctx.qualify)) 282 fmt.Fprintf(&b, "if err := dec.ReadBytes(%s[:]); err != nil { return err }\n", resultV) 283 return resultV, b.String() 284 } 285 286 // bigIntOp handles big.Int. 287 // This exists because big.Int has it's own decoder operation on rlp.Stream, 288 // but the decode method returns *big.Int, so it needs to be dereferenced. 289 type bigIntOp struct { 290 pointer bool 291 } 292 293 func (op bigIntOp) genWrite(ctx *genContext, v string) string { 294 var b bytes.Buffer 295 296 fmt.Fprintf(&b, "if %s.Sign() == -1 {\n", v) 297 fmt.Fprintf(&b, " return rlp.ErrNegativeBigInt\n") 298 fmt.Fprintf(&b, "}\n") 299 dst := v 300 if !op.pointer { 301 dst = "&" + v 302 } 303 fmt.Fprintf(&b, "w.WriteBigInt(%s)\n", dst) 304 305 // Wrap with nil check. 306 if op.pointer { 307 code := b.String() 308 b.Reset() 309 fmt.Fprintf(&b, "if %s == nil {\n", v) 310 fmt.Fprintf(&b, " w.Write(rlp.EmptyString)") 311 fmt.Fprintf(&b, "} else {\n") 312 fmt.Fprint(&b, code) 313 fmt.Fprintf(&b, "}\n") 314 } 315 316 return b.String() 317 } 318 319 func (op bigIntOp) genDecode(ctx *genContext) (string, string) { 320 var resultV = ctx.temp() 321 322 var b bytes.Buffer 323 fmt.Fprintf(&b, "%s, err := dec.BigInt()\n", resultV) 324 fmt.Fprintf(&b, "if err != nil { return err }\n") 325 326 result := resultV 327 if !op.pointer { 328 result = "(*" + resultV + ")" 329 } 330 return result, b.String() 331 } 332 333 // uint256Op handles "github.com/holiman/uint256".Int 334 type uint256Op struct { 335 pointer bool 336 } 337 338 func (op uint256Op) genWrite(ctx *genContext, v string) string { 339 var b bytes.Buffer 340 341 dst := v 342 if !op.pointer { 343 dst = "&" + v 344 } 345 fmt.Fprintf(&b, "w.WriteUint256(%s)\n", dst) 346 347 // Wrap with nil check. 348 if op.pointer { 349 code := b.String() 350 b.Reset() 351 fmt.Fprintf(&b, "if %s == nil {\n", v) 352 fmt.Fprintf(&b, " w.Write(rlp.EmptyString)") 353 fmt.Fprintf(&b, "} else {\n") 354 fmt.Fprint(&b, code) 355 fmt.Fprintf(&b, "}\n") 356 } 357 358 return b.String() 359 } 360 361 func (op uint256Op) genDecode(ctx *genContext) (string, string) { 362 ctx.addImport("github.com/holiman/uint256") 363 364 var b bytes.Buffer 365 resultV := ctx.temp() 366 fmt.Fprintf(&b, "var %s uint256.Int\n", resultV) 367 fmt.Fprintf(&b, "if err := dec.ReadUint256(&%s); err != nil { return err }\n", resultV) 368 369 result := resultV 370 if op.pointer { 371 result = "&" + resultV 372 } 373 return result, b.String() 374 } 375 376 // encoderDecoderOp handles rlp.Encoder and rlp.Decoder. 377 // In order to be used with this, the type must implement both interfaces. 378 // This restriction may be lifted in the future by creating separate ops for 379 // encoding and decoding. 380 type encoderDecoderOp struct { 381 typ types.Type 382 } 383 384 func (op encoderDecoderOp) genWrite(ctx *genContext, v string) string { 385 return fmt.Sprintf("if err := %s.EncodeRLP(w); err != nil { return err }\n", v) 386 } 387 388 func (op encoderDecoderOp) genDecode(ctx *genContext) (string, string) { 389 // DecodeRLP must have pointer receiver, and this is verified in makeOp. 390 etyp := op.typ.(*types.Pointer).Elem() 391 var resultV = ctx.temp() 392 393 var b bytes.Buffer 394 fmt.Fprintf(&b, "%s := new(%s)\n", resultV, types.TypeString(etyp, ctx.qualify)) 395 fmt.Fprintf(&b, "if err := %s.DecodeRLP(dec); err != nil { return err }\n", resultV) 396 return resultV, b.String() 397 } 398 399 // ptrOp handles pointer types. 400 type ptrOp struct { 401 elemTyp types.Type 402 elem op 403 nilOK bool 404 nilValue rlpstruct.NilKind 405 } 406 407 func (bctx *buildContext) makePtrOp(elemTyp types.Type, tags rlpstruct.Tags) (op, error) { 408 elemOp, err := bctx.makeOp(nil, elemTyp, rlpstruct.Tags{}) 409 if err != nil { 410 return nil, err 411 } 412 op := ptrOp{elemTyp: elemTyp, elem: elemOp} 413 414 // Determine nil value. 415 if tags.NilOK { 416 op.nilOK = true 417 op.nilValue = tags.NilKind 418 } else { 419 styp := bctx.typeToStructType(elemTyp) 420 op.nilValue = styp.DefaultNilValue() 421 } 422 return op, nil 423 } 424 425 func (op ptrOp) genWrite(ctx *genContext, v string) string { 426 // Note: in writer functions, accesses to v are read-only, i.e. v is any Go 427 // expression. To make all accesses work through the pointer, we substitute 428 // v with (*v). This is required for most accesses including `v`, `call(v)`, 429 // and `v[index]` on slices. 430 // 431 // For `v.field` and `v[:]` on arrays, the dereference operation is not required. 432 var vv string 433 _, isStruct := op.elem.(structOp) 434 _, isByteArray := op.elem.(byteArrayOp) 435 if isStruct || isByteArray { 436 vv = v 437 } else { 438 vv = fmt.Sprintf("(*%s)", v) 439 } 440 441 var b bytes.Buffer 442 fmt.Fprintf(&b, "if %s == nil {\n", v) 443 fmt.Fprintf(&b, " w.Write([]byte{0x%X})\n", op.nilValue) 444 fmt.Fprintf(&b, "} else {\n") 445 fmt.Fprintf(&b, " %s", op.elem.genWrite(ctx, vv)) 446 fmt.Fprintf(&b, "}\n") 447 return b.String() 448 } 449 450 func (op ptrOp) genDecode(ctx *genContext) (string, string) { 451 result, code := op.elem.genDecode(ctx) 452 if !op.nilOK { 453 // If nil pointers are not allowed, we can just decode the element. 454 return "&" + result, code 455 } 456 457 // nil is allowed, so check the kind and size first. 458 // If size is zero and kind matches the nilKind of the type, 459 // the value decodes as a nil pointer. 460 var ( 461 resultV = ctx.temp() 462 kindV = ctx.temp() 463 sizeV = ctx.temp() 464 wantKind string 465 ) 466 if op.nilValue == rlpstruct.NilKindList { 467 wantKind = "rlp.List" 468 } else { 469 wantKind = "rlp.String" 470 } 471 var b bytes.Buffer 472 fmt.Fprintf(&b, "var %s %s\n", resultV, types.TypeString(types.NewPointer(op.elemTyp), ctx.qualify)) 473 fmt.Fprintf(&b, "if %s, %s, err := dec.Kind(); err != nil {\n", kindV, sizeV) 474 fmt.Fprintf(&b, " return err\n") 475 fmt.Fprintf(&b, "} else if %s != 0 || %s != %s {\n", sizeV, kindV, wantKind) 476 fmt.Fprint(&b, code) 477 fmt.Fprintf(&b, " %s = &%s\n", resultV, result) 478 fmt.Fprintf(&b, "}\n") 479 return resultV, b.String() 480 } 481 482 // structOp handles struct types. 483 type structOp struct { 484 named *types.Named 485 typ *types.Struct 486 fields []*structField 487 optionalFields []*structField 488 } 489 490 type structField struct { 491 name string 492 typ types.Type 493 elem op 494 } 495 496 func (bctx *buildContext) makeStructOp(named *types.Named, typ *types.Struct) (op, error) { 497 // Convert fields to []rlpstruct.Field. 498 var allStructFields []rlpstruct.Field 499 for i := 0; i < typ.NumFields(); i++ { 500 f := typ.Field(i) 501 allStructFields = append(allStructFields, rlpstruct.Field{ 502 Name: f.Name(), 503 Exported: f.Exported(), 504 Index: i, 505 Tag: typ.Tag(i), 506 Type: *bctx.typeToStructType(f.Type()), 507 }) 508 } 509 510 // Filter/validate fields. 511 fields, tags, err := rlpstruct.ProcessFields(allStructFields) 512 if err != nil { 513 return nil, err 514 } 515 516 // Create field ops. 517 var op = structOp{named: named, typ: typ} 518 for i, field := range fields { 519 // Advanced struct tags are not supported yet. 520 tag := tags[i] 521 if err := checkUnsupportedTags(field.Name, tag); err != nil { 522 return nil, err 523 } 524 typ := typ.Field(field.Index).Type() 525 elem, err := bctx.makeOp(nil, typ, tags[i]) 526 if err != nil { 527 return nil, fmt.Errorf("field %s: %v", field.Name, err) 528 } 529 f := &structField{name: field.Name, typ: typ, elem: elem} 530 if tag.Optional { 531 op.optionalFields = append(op.optionalFields, f) 532 } else { 533 op.fields = append(op.fields, f) 534 } 535 } 536 return op, nil 537 } 538 539 func checkUnsupportedTags(field string, tag rlpstruct.Tags) error { 540 if tag.Tail { 541 return fmt.Errorf(`field %s has unsupported struct tag "tail"`, field) 542 } 543 return nil 544 } 545 546 func (op structOp) genWrite(ctx *genContext, v string) string { 547 var b bytes.Buffer 548 var listMarker = ctx.temp() 549 fmt.Fprintf(&b, "%s := w.List()\n", listMarker) 550 for _, field := range op.fields { 551 selector := v + "." + field.name 552 fmt.Fprint(&b, field.elem.genWrite(ctx, selector)) 553 } 554 op.writeOptionalFields(&b, ctx, v) 555 fmt.Fprintf(&b, "w.ListEnd(%s)\n", listMarker) 556 return b.String() 557 } 558 559 func (op structOp) writeOptionalFields(b *bytes.Buffer, ctx *genContext, v string) { 560 if len(op.optionalFields) == 0 { 561 return 562 } 563 // First check zero-ness of all optional fields. 564 var zeroV = make([]string, len(op.optionalFields)) 565 for i, field := range op.optionalFields { 566 selector := v + "." + field.name 567 zeroV[i] = ctx.temp() 568 fmt.Fprintf(b, "%s := %s\n", zeroV[i], nonZeroCheck(selector, field.typ, ctx.qualify)) 569 } 570 // Now write the fields. 571 for i, field := range op.optionalFields { 572 selector := v + "." + field.name 573 cond := "" 574 for j := i; j < len(op.optionalFields); j++ { 575 if j > i { 576 cond += " || " 577 } 578 cond += zeroV[j] 579 } 580 fmt.Fprintf(b, "if %s {\n", cond) 581 fmt.Fprint(b, field.elem.genWrite(ctx, selector)) 582 fmt.Fprintf(b, "}\n") 583 } 584 } 585 586 func (op structOp) genDecode(ctx *genContext) (string, string) { 587 // Get the string representation of the type. 588 // Here, named types are handled separately because the output 589 // would contain a copy of the struct definition otherwise. 590 var typeName string 591 if op.named != nil { 592 typeName = types.TypeString(op.named, ctx.qualify) 593 } else { 594 typeName = types.TypeString(op.typ, ctx.qualify) 595 } 596 597 // Create struct object. 598 var resultV = ctx.temp() 599 var b bytes.Buffer 600 fmt.Fprintf(&b, "var %s %s\n", resultV, typeName) 601 602 // Decode fields. 603 fmt.Fprintf(&b, "{\n") 604 fmt.Fprintf(&b, "if _, err := dec.List(); err != nil { return err }\n") 605 for _, field := range op.fields { 606 result, code := field.elem.genDecode(ctx) 607 fmt.Fprintf(&b, "// %s:\n", field.name) 608 fmt.Fprint(&b, code) 609 fmt.Fprintf(&b, "%s.%s = %s\n", resultV, field.name, result) 610 } 611 op.decodeOptionalFields(&b, ctx, resultV) 612 fmt.Fprintf(&b, "if err := dec.ListEnd(); err != nil { return err }\n") 613 fmt.Fprintf(&b, "}\n") 614 return resultV, b.String() 615 } 616 617 func (op structOp) decodeOptionalFields(b *bytes.Buffer, ctx *genContext, resultV string) { 618 var suffix bytes.Buffer 619 for _, field := range op.optionalFields { 620 result, code := field.elem.genDecode(ctx) 621 fmt.Fprintf(b, "// %s:\n", field.name) 622 fmt.Fprintf(b, "if dec.MoreDataInList() {\n") 623 fmt.Fprint(b, code) 624 fmt.Fprintf(b, "%s.%s = %s\n", resultV, field.name, result) 625 fmt.Fprintf(&suffix, "}\n") 626 } 627 suffix.WriteTo(b) 628 } 629 630 // sliceOp handles slice types. 631 type sliceOp struct { 632 typ *types.Slice 633 elemOp op 634 } 635 636 func (bctx *buildContext) makeSliceOp(typ *types.Slice) (op, error) { 637 elemOp, err := bctx.makeOp(nil, typ.Elem(), rlpstruct.Tags{}) 638 if err != nil { 639 return nil, err 640 } 641 return sliceOp{typ: typ, elemOp: elemOp}, nil 642 } 643 644 func (op sliceOp) genWrite(ctx *genContext, v string) string { 645 var ( 646 listMarker = ctx.temp() // holds return value of w.List() 647 iterElemV = ctx.temp() // iteration variable 648 elemCode = op.elemOp.genWrite(ctx, iterElemV) 649 ) 650 651 var b bytes.Buffer 652 fmt.Fprintf(&b, "%s := w.List()\n", listMarker) 653 fmt.Fprintf(&b, "for _, %s := range %s {\n", iterElemV, v) 654 fmt.Fprint(&b, elemCode) 655 fmt.Fprintf(&b, "}\n") 656 fmt.Fprintf(&b, "w.ListEnd(%s)\n", listMarker) 657 return b.String() 658 } 659 660 func (op sliceOp) genDecode(ctx *genContext) (string, string) { 661 var sliceV = ctx.temp() // holds the output slice 662 elemResult, elemCode := op.elemOp.genDecode(ctx) 663 664 var b bytes.Buffer 665 fmt.Fprintf(&b, "var %s %s\n", sliceV, types.TypeString(op.typ, ctx.qualify)) 666 fmt.Fprintf(&b, "if _, err := dec.List(); err != nil { return err }\n") 667 fmt.Fprintf(&b, "for dec.MoreDataInList() {\n") 668 fmt.Fprintf(&b, " %s", elemCode) 669 fmt.Fprintf(&b, " %s = append(%s, %s)\n", sliceV, sliceV, elemResult) 670 fmt.Fprintf(&b, "}\n") 671 fmt.Fprintf(&b, "if err := dec.ListEnd(); err != nil { return err }\n") 672 return sliceV, b.String() 673 } 674 675 func (bctx *buildContext) makeOp(name *types.Named, typ types.Type, tags rlpstruct.Tags) (op, error) { 676 switch typ := typ.(type) { 677 case *types.Named: 678 if isBigInt(typ) { 679 return bigIntOp{}, nil 680 } 681 if isUint256(typ) { 682 return uint256Op{}, nil 683 } 684 if typ == bctx.rawValueType { 685 return bctx.makeRawValueOp(), nil 686 } 687 if bctx.isDecoder(typ) { 688 return nil, fmt.Errorf("type %v implements rlp.Decoder with non-pointer receiver", typ) 689 } 690 // TODO: same check for encoder? 691 return bctx.makeOp(typ, typ.Underlying(), tags) 692 case *types.Pointer: 693 if isBigInt(typ.Elem()) { 694 return bigIntOp{pointer: true}, nil 695 } 696 if isUint256(typ.Elem()) { 697 return uint256Op{pointer: true}, nil 698 } 699 // Encoder/Decoder interfaces. 700 if bctx.isEncoder(typ) { 701 if bctx.isDecoder(typ) { 702 return encoderDecoderOp{typ}, nil 703 } 704 return nil, fmt.Errorf("type %v implements rlp.Encoder but not rlp.Decoder", typ) 705 } 706 if bctx.isDecoder(typ) { 707 return nil, fmt.Errorf("type %v implements rlp.Decoder but not rlp.Encoder", typ) 708 } 709 // Default pointer handling. 710 return bctx.makePtrOp(typ.Elem(), tags) 711 case *types.Basic: 712 return bctx.makeBasicOp(typ) 713 case *types.Struct: 714 return bctx.makeStructOp(name, typ) 715 case *types.Slice: 716 etyp := typ.Elem() 717 if isByte(etyp) && !bctx.isEncoder(etyp) { 718 return bctx.makeByteSliceOp(typ), nil 719 } 720 return bctx.makeSliceOp(typ) 721 case *types.Array: 722 etyp := typ.Elem() 723 if isByte(etyp) && !bctx.isEncoder(etyp) { 724 return bctx.makeByteArrayOp(name, typ), nil 725 } 726 return nil, fmt.Errorf("unhandled array type: %v", typ) 727 default: 728 return nil, fmt.Errorf("unhandled type: %v", typ) 729 } 730 } 731 732 // generateDecoder generates the DecodeRLP method on 'typ'. 733 func generateDecoder(ctx *genContext, typ string, op op) []byte { 734 ctx.resetTemp() 735 ctx.addImport(pathOfPackageRLP) 736 737 result, code := op.genDecode(ctx) 738 var b bytes.Buffer 739 fmt.Fprintf(&b, "func (obj *%s) DecodeRLP(dec *rlp.Stream) error {\n", typ) 740 fmt.Fprint(&b, code) 741 fmt.Fprintf(&b, " *obj = %s\n", result) 742 fmt.Fprintf(&b, " return nil\n") 743 fmt.Fprintf(&b, "}\n") 744 return b.Bytes() 745 } 746 747 // generateEncoder generates the EncodeRLP method on 'typ'. 748 func generateEncoder(ctx *genContext, typ string, op op) []byte { 749 ctx.resetTemp() 750 ctx.addImport("io") 751 ctx.addImport(pathOfPackageRLP) 752 753 var b bytes.Buffer 754 fmt.Fprintf(&b, "func (obj *%s) EncodeRLP(_w io.Writer) error {\n", typ) 755 fmt.Fprintf(&b, " w := rlp.NewEncoderBuffer(_w)\n") 756 fmt.Fprint(&b, op.genWrite(ctx, "obj")) 757 fmt.Fprintf(&b, " return w.Flush()\n") 758 fmt.Fprintf(&b, "}\n") 759 return b.Bytes() 760 } 761 762 func (bctx *buildContext) generate(typ *types.Named, encoder, decoder bool) ([]byte, error) { 763 bctx.topType = typ 764 765 pkg := typ.Obj().Pkg() 766 op, err := bctx.makeOp(nil, typ, rlpstruct.Tags{}) 767 if err != nil { 768 return nil, err 769 } 770 771 var ( 772 ctx = newGenContext(pkg) 773 encSource []byte 774 decSource []byte 775 ) 776 if encoder { 777 encSource = generateEncoder(ctx, typ.Obj().Name(), op) 778 } 779 if decoder { 780 decSource = generateDecoder(ctx, typ.Obj().Name(), op) 781 } 782 783 var b bytes.Buffer 784 fmt.Fprintf(&b, "package %s\n\n", pkg.Name()) 785 for _, imp := range ctx.importsList() { 786 fmt.Fprintf(&b, "import %q\n", imp) 787 } 788 if encoder { 789 fmt.Fprintln(&b) 790 b.Write(encSource) 791 } 792 if decoder { 793 fmt.Fprintln(&b) 794 b.Write(decSource) 795 } 796 797 source := b.Bytes() 798 // fmt.Println(string(source)) 799 return format.Source(source) 800 }