Skip to content

Commit 7855014

Browse files
committed
feat: support underlying basic types in rlpgen
1 parent 414b1f5 commit 7855014

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

rlp/rlpgen/gen.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,30 @@ func (op uint256Op) genDecode(ctx *genContext) (string, string) {
373373
return result, b.String()
374374
}
375375

376+
func (bctx *buildContext) makeNamedBasicOp(named *types.Named) (op, error) {
377+
underlying := named.Underlying()
378+
basic, ok := underlying.(*types.Basic)
379+
if !ok {
380+
return nil, fmt.Errorf("expected basic type, got %T", underlying)
381+
}
382+
383+
// Use the existing makeBasicOp function to get the base operation
384+
baseOp, err := bctx.makeBasicOp(basic)
385+
if err != nil {
386+
return nil, err
387+
}
388+
389+
// Cast to basicOp and modify the typ field to use the named type
390+
op := baseOp.(basicOp)
391+
op.typ = named // Use the named type as the main type instead of the underlying basic type
392+
393+
// For decoding, we want to decode as the underlying basic type and convert to named type
394+
// So we need to set decResultType to the underlying basic type
395+
op.decResultType = basic
396+
397+
return op, nil
398+
}
399+
376400
// encoderDecoderOp handles rlp.Encoder and rlp.Decoder.
377401
// In order to be used with this, the type must implement both interfaces.
378402
// This restriction may be lifted in the future by creating separate ops for
@@ -684,6 +708,9 @@ func (bctx *buildContext) makeOp(name *types.Named, typ types.Type, tags rlpstru
684708
if typ == bctx.rawValueType {
685709
return bctx.makeRawValueOp(), nil
686710
}
711+
if isNamedWithBasicUnderlying(typ) {
712+
return bctx.makeNamedBasicOp(typ)
713+
}
687714
if bctx.isDecoder(typ) {
688715
return nil, fmt.Errorf("type %v implements rlp.Decoder with non-pointer receiver", typ)
689716
}

rlp/rlpgen/testdata/alias.in.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ type (
1414
// Demonstrate recursive unaliasing
1515
intermediate = uint256.Int
1616
Uint256 = intermediate
17+
Uint64T uint64 // This is not an alias, it's a new type
1718
)
1819

1920
type Test struct {
2021
BigAlias Big
2122
Uint256Alias Uint256
23+
Uint64NewT Uint64T
2224
}

rlp/rlpgen/testdata/alias.out.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ func (obj *Test) EncodeRLP(_w io.Writer) error {
1212
}
1313
w.WriteBigInt(&obj.BigAlias)
1414
w.WriteUint256(&obj.Uint256Alias)
15+
w.WriteUint64(uint64(obj.Uint64NewT))
1516
w.ListEnd(_tmp0)
1617
return w.Flush()
1718
}
@@ -34,6 +35,13 @@ func (obj *Test) DecodeRLP(dec *rlp.Stream) error {
3435
return err
3536
}
3637
_tmp0.Uint256Alias = _tmp2
38+
// Uint64NewT:
39+
_tmp3, err := dec.Uint64()
40+
if err != nil {
41+
return err
42+
}
43+
_tmp4 := Uint64T(_tmp3)
44+
_tmp0.Uint64NewT = _tmp4
3745
if err := dec.ListEnd(); err != nil {
3846
return err
3947
}

rlp/rlpgen/types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ func isByte(typ types.Type) bool {
113113
return ok && basic.Kind() == types.Uint8
114114
}
115115

116+
// isNamedWithBasicUnderlying checks whether 'typ' is a named type with an underlying basic type.
117+
func isNamedWithBasicUnderlying(typ types.Type) bool {
118+
named, ok := typ.(*types.Named)
119+
if !ok {
120+
return false
121+
}
122+
_, ok = named.Underlying().(*types.Basic)
123+
return ok
124+
}
125+
116126
func resolveUnderlying(typ types.Type) types.Type {
117127
for {
118128
t := typ.Underlying()

0 commit comments

Comments
 (0)