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  }