github.com/jimmyx0x/go-ethereum@v1.10.28/rlp/encode_test.go (about)

     1  // Copyright 2014 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 rlp
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"io"
    24  	"math/big"
    25  	"runtime"
    26  	"sync"
    27  	"testing"
    28  
    29  	"github.com/ethereum/go-ethereum/common/math"
    30  )
    31  
    32  type testEncoder struct {
    33  	err error
    34  }
    35  
    36  func (e *testEncoder) EncodeRLP(w io.Writer) error {
    37  	if e == nil {
    38  		panic("EncodeRLP called on nil value")
    39  	}
    40  	if e.err != nil {
    41  		return e.err
    42  	}
    43  	w.Write([]byte{0, 1, 0, 1, 0, 1, 0, 1, 0, 1})
    44  	return nil
    45  }
    46  
    47  type testEncoderValueMethod struct{}
    48  
    49  func (e testEncoderValueMethod) EncodeRLP(w io.Writer) error {
    50  	w.Write([]byte{0xFA, 0xFE, 0xF0})
    51  	return nil
    52  }
    53  
    54  type byteEncoder byte
    55  
    56  func (e byteEncoder) EncodeRLP(w io.Writer) error {
    57  	w.Write(EmptyList)
    58  	return nil
    59  }
    60  
    61  type undecodableEncoder func()
    62  
    63  func (f undecodableEncoder) EncodeRLP(w io.Writer) error {
    64  	w.Write([]byte{0xF5, 0xF5, 0xF5})
    65  	return nil
    66  }
    67  
    68  type encodableReader struct {
    69  	A, B uint
    70  }
    71  
    72  func (e *encodableReader) Read(b []byte) (int, error) {
    73  	panic("called")
    74  }
    75  
    76  type namedByteType byte
    77  
    78  var (
    79  	_ = Encoder(&testEncoder{})
    80  	_ = Encoder(byteEncoder(0))
    81  
    82  	reader io.Reader = &encodableReader{1, 2}
    83  )
    84  
    85  type encTest struct {
    86  	val           interface{}
    87  	output, error string
    88  }
    89  
    90  var encTests = []encTest{
    91  	// booleans
    92  	{val: true, output: "01"},
    93  	{val: false, output: "80"},
    94  
    95  	// integers
    96  	{val: uint32(0), output: "80"},
    97  	{val: uint32(127), output: "7F"},
    98  	{val: uint32(128), output: "8180"},
    99  	{val: uint32(256), output: "820100"},
   100  	{val: uint32(1024), output: "820400"},
   101  	{val: uint32(0xFFFFFF), output: "83FFFFFF"},
   102  	{val: uint32(0xFFFFFFFF), output: "84FFFFFFFF"},
   103  	{val: uint64(0xFFFFFFFF), output: "84FFFFFFFF"},
   104  	{val: uint64(0xFFFFFFFFFF), output: "85FFFFFFFFFF"},
   105  	{val: uint64(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"},
   106  	{val: uint64(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"},
   107  	{val: uint64(0xFFFFFFFFFFFFFFFF), output: "88FFFFFFFFFFFFFFFF"},
   108  
   109  	// big integers (should match uint for small values)
   110  	{val: big.NewInt(0), output: "80"},
   111  	{val: big.NewInt(1), output: "01"},
   112  	{val: big.NewInt(127), output: "7F"},
   113  	{val: big.NewInt(128), output: "8180"},
   114  	{val: big.NewInt(256), output: "820100"},
   115  	{val: big.NewInt(1024), output: "820400"},
   116  	{val: big.NewInt(0xFFFFFF), output: "83FFFFFF"},
   117  	{val: big.NewInt(0xFFFFFFFF), output: "84FFFFFFFF"},
   118  	{val: big.NewInt(0xFFFFFFFFFF), output: "85FFFFFFFFFF"},
   119  	{val: big.NewInt(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"},
   120  	{val: big.NewInt(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"},
   121  	{
   122  		val:    new(big.Int).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")),
   123  		output: "8F102030405060708090A0B0C0D0E0F2",
   124  	},
   125  	{
   126  		val:    new(big.Int).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")),
   127  		output: "9C0100020003000400050006000700080009000A000B000C000D000E01",
   128  	},
   129  	{
   130  		val:    new(big.Int).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")),
   131  		output: "A1010000000000000000000000000000000000000000000000000000000000000000",
   132  	},
   133  	{
   134  		val:    veryBigInt,
   135  		output: "89FFFFFFFFFFFFFFFFFF",
   136  	},
   137  	{
   138  		val:    veryVeryBigInt,
   139  		output: "B848FFFFFFFFFFFFFFFFF800000000000000001BFFFFFFFFFFFFFFFFC8000000000000000045FFFFFFFFFFFFFFFFC800000000000000001BFFFFFFFFFFFFFFFFF8000000000000000001",
   140  	},
   141  
   142  	// non-pointer big.Int
   143  	{val: *big.NewInt(0), output: "80"},
   144  	{val: *big.NewInt(0xFFFFFF), output: "83FFFFFF"},
   145  
   146  	// negative ints are not supported
   147  	{val: big.NewInt(-1), error: "rlp: cannot encode negative big.Int"},
   148  	{val: *big.NewInt(-1), error: "rlp: cannot encode negative big.Int"},
   149  
   150  	// byte arrays
   151  	{val: [0]byte{}, output: "80"},
   152  	{val: [1]byte{0}, output: "00"},
   153  	{val: [1]byte{1}, output: "01"},
   154  	{val: [1]byte{0x7F}, output: "7F"},
   155  	{val: [1]byte{0x80}, output: "8180"},
   156  	{val: [1]byte{0xFF}, output: "81FF"},
   157  	{val: [3]byte{1, 2, 3}, output: "83010203"},
   158  	{val: [57]byte{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
   159  
   160  	// named byte type arrays
   161  	{val: [0]namedByteType{}, output: "80"},
   162  	{val: [1]namedByteType{0}, output: "00"},
   163  	{val: [1]namedByteType{1}, output: "01"},
   164  	{val: [1]namedByteType{0x7F}, output: "7F"},
   165  	{val: [1]namedByteType{0x80}, output: "8180"},
   166  	{val: [1]namedByteType{0xFF}, output: "81FF"},
   167  	{val: [3]namedByteType{1, 2, 3}, output: "83010203"},
   168  	{val: [57]namedByteType{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
   169  
   170  	// byte slices
   171  	{val: []byte{}, output: "80"},
   172  	{val: []byte{0}, output: "00"},
   173  	{val: []byte{0x7E}, output: "7E"},
   174  	{val: []byte{0x7F}, output: "7F"},
   175  	{val: []byte{0x80}, output: "8180"},
   176  	{val: []byte{1, 2, 3}, output: "83010203"},
   177  
   178  	// named byte type slices
   179  	{val: []namedByteType{}, output: "80"},
   180  	{val: []namedByteType{0}, output: "00"},
   181  	{val: []namedByteType{0x7E}, output: "7E"},
   182  	{val: []namedByteType{0x7F}, output: "7F"},
   183  	{val: []namedByteType{0x80}, output: "8180"},
   184  	{val: []namedByteType{1, 2, 3}, output: "83010203"},
   185  
   186  	// strings
   187  	{val: "", output: "80"},
   188  	{val: "\x7E", output: "7E"},
   189  	{val: "\x7F", output: "7F"},
   190  	{val: "\x80", output: "8180"},
   191  	{val: "dog", output: "83646F67"},
   192  	{
   193  		val:    "Lorem ipsum dolor sit amet, consectetur adipisicing eli",
   194  		output: "B74C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C69",
   195  	},
   196  	{
   197  		val:    "Lorem ipsum dolor sit amet, consectetur adipisicing elit",
   198  		output: "B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974",
   199  	},
   200  	{
   201  		val:    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat",
   202  		output: "B904004C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742E20437572616269747572206D6175726973206D61676E612C20737573636970697420736564207665686963756C61206E6F6E2C20696163756C697320666175636962757320746F72746F722E2050726F696E20737573636970697420756C74726963696573206D616C6573756164612E204475697320746F72746F7220656C69742C2064696374756D2071756973207472697374697175652065752C20756C7472696365732061742072697375732E204D6F72626920612065737420696D70657264696574206D6920756C6C616D636F7270657220616C6971756574207375736369706974206E6563206C6F72656D2E2041656E65616E2071756973206C656F206D6F6C6C69732C2076756C70757461746520656C6974207661726975732C20636F6E73657175617420656E696D2E204E756C6C6120756C74726963657320747572706973206A7573746F2C20657420706F73756572652075726E6120636F6E7365637465747572206E65632E2050726F696E206E6F6E20636F6E76616C6C6973206D657475732E20446F6E65632074656D706F7220697073756D20696E206D617572697320636F6E67756520736F6C6C696369747564696E2E20566573746962756C756D20616E746520697073756D207072696D697320696E206661756369627573206F726369206C756374757320657420756C74726963657320706F737565726520637562696C69612043757261653B2053757370656E646973736520636F6E76616C6C69732073656D2076656C206D617373612066617563696275732C2065676574206C6163696E6961206C616375732074656D706F722E204E756C6C61207175697320756C747269636965732070757275732E2050726F696E20617563746F722072686F6E637573206E69626820636F6E64696D656E74756D206D6F6C6C69732E20416C697175616D20636F6E73657175617420656E696D206174206D65747573206C75637475732C206120656C656966656E6420707572757320656765737461732E20437572616269747572206174206E696268206D657475732E204E616D20626962656E64756D2C206E6571756520617420617563746F72207472697374697175652C206C6F72656D206C696265726F20616C697175657420617263752C206E6F6E20696E74657264756D2074656C6C7573206C65637475732073697420616D65742065726F732E20437261732072686F6E6375732C206D65747573206163206F726E617265206375727375732C20646F6C6F72206A7573746F20756C747269636573206D657475732C20617420756C6C616D636F7270657220766F6C7574706174",
   203  	},
   204  
   205  	// slices
   206  	{val: []uint{}, output: "C0"},
   207  	{val: []uint{1, 2, 3}, output: "C3010203"},
   208  	{
   209  		// [ [], [[]], [ [], [[]] ] ]
   210  		val:    []interface{}{[]interface{}{}, [][]interface{}{{}}, []interface{}{[]interface{}{}, [][]interface{}{{}}}},
   211  		output: "C7C0C1C0C3C0C1C0",
   212  	},
   213  	{
   214  		val:    []string{"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo"},
   215  		output: "F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F",
   216  	},
   217  	{
   218  		val:    []interface{}{uint(1), uint(0xFFFFFF), []interface{}{[]uint{4, 5, 5}}, "abc"},
   219  		output: "CE0183FFFFFFC4C304050583616263",
   220  	},
   221  	{
   222  		val: [][]string{
   223  			{"asdf", "qwer", "zxcv"},
   224  			{"asdf", "qwer", "zxcv"},
   225  			{"asdf", "qwer", "zxcv"},
   226  			{"asdf", "qwer", "zxcv"},
   227  			{"asdf", "qwer", "zxcv"},
   228  			{"asdf", "qwer", "zxcv"},
   229  			{"asdf", "qwer", "zxcv"},
   230  			{"asdf", "qwer", "zxcv"},
   231  			{"asdf", "qwer", "zxcv"},
   232  			{"asdf", "qwer", "zxcv"},
   233  			{"asdf", "qwer", "zxcv"},
   234  			{"asdf", "qwer", "zxcv"},
   235  			{"asdf", "qwer", "zxcv"},
   236  			{"asdf", "qwer", "zxcv"},
   237  			{"asdf", "qwer", "zxcv"},
   238  			{"asdf", "qwer", "zxcv"},
   239  			{"asdf", "qwer", "zxcv"},
   240  			{"asdf", "qwer", "zxcv"},
   241  			{"asdf", "qwer", "zxcv"},
   242  			{"asdf", "qwer", "zxcv"},
   243  			{"asdf", "qwer", "zxcv"},
   244  			{"asdf", "qwer", "zxcv"},
   245  			{"asdf", "qwer", "zxcv"},
   246  			{"asdf", "qwer", "zxcv"},
   247  			{"asdf", "qwer", "zxcv"},
   248  			{"asdf", "qwer", "zxcv"},
   249  			{"asdf", "qwer", "zxcv"},
   250  			{"asdf", "qwer", "zxcv"},
   251  			{"asdf", "qwer", "zxcv"},
   252  			{"asdf", "qwer", "zxcv"},
   253  			{"asdf", "qwer", "zxcv"},
   254  			{"asdf", "qwer", "zxcv"},
   255  		},
   256  		output: "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376",
   257  	},
   258  
   259  	// RawValue
   260  	{val: RawValue(unhex("01")), output: "01"},
   261  	{val: RawValue(unhex("82FFFF")), output: "82FFFF"},
   262  	{val: []RawValue{unhex("01"), unhex("02")}, output: "C20102"},
   263  
   264  	// structs
   265  	{val: simplestruct{}, output: "C28080"},
   266  	{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},
   267  	{val: &recstruct{5, nil}, output: "C205C0"},
   268  	{val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"},
   269  	{val: &intField{X: 3}, error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)"},
   270  
   271  	// struct tag "-"
   272  	{val: &ignoredField{A: 1, B: 2, C: 3}, output: "C20103"},
   273  
   274  	// struct tag "tail"
   275  	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"},
   276  	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
   277  	{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
   278  	{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
   279  
   280  	// struct tag "optional"
   281  	{val: &optionalFields{}, output: "C180"},
   282  	{val: &optionalFields{A: 1}, output: "C101"},
   283  	{val: &optionalFields{A: 1, B: 2}, output: "C20102"},
   284  	{val: &optionalFields{A: 1, B: 2, C: 3}, output: "C3010203"},
   285  	{val: &optionalFields{A: 1, B: 0, C: 3}, output: "C3018003"},
   286  	{val: &optionalAndTailField{A: 1}, output: "C101"},
   287  	{val: &optionalAndTailField{A: 1, B: 2}, output: "C20102"},
   288  	{val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
   289  	{val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
   290  	{val: &optionalBigIntField{A: 1}, output: "C101"},
   291  	{val: &optionalPtrField{A: 1}, output: "C101"},
   292  	{val: &optionalPtrFieldNil{A: 1}, output: "C101"},
   293  	{val: &multipleOptionalFields{A: nil, B: nil}, output: "C0"},
   294  	{val: &multipleOptionalFields{A: &[3]byte{1, 2, 3}, B: &[3]byte{1, 2, 3}}, output: "C88301020383010203"},
   295  	{val: &multipleOptionalFields{A: nil, B: &[3]byte{1, 2, 3}}, output: "C58083010203"}, // encodes without error but decode will fail
   296  	{val: &nonOptionalPtrField{A: 1}, output: "C20180"},                                  // encodes without error but decode will fail
   297  
   298  	// nil
   299  	{val: (*uint)(nil), output: "80"},
   300  	{val: (*string)(nil), output: "80"},
   301  	{val: (*[]byte)(nil), output: "80"},
   302  	{val: (*[10]byte)(nil), output: "80"},
   303  	{val: (*big.Int)(nil), output: "80"},
   304  	{val: (*[]string)(nil), output: "C0"},
   305  	{val: (*[10]string)(nil), output: "C0"},
   306  	{val: (*[]interface{})(nil), output: "C0"},
   307  	{val: (*[]struct{ uint })(nil), output: "C0"},
   308  	{val: (*interface{})(nil), output: "C0"},
   309  
   310  	// nil struct fields
   311  	{
   312  		val: struct {
   313  			X *[]byte
   314  		}{},
   315  		output: "C180",
   316  	},
   317  	{
   318  		val: struct {
   319  			X *[2]byte
   320  		}{},
   321  		output: "C180",
   322  	},
   323  	{
   324  		val: struct {
   325  			X *uint64
   326  		}{},
   327  		output: "C180",
   328  	},
   329  	{
   330  		val: struct {
   331  			X *uint64 `rlp:"nilList"`
   332  		}{},
   333  		output: "C1C0",
   334  	},
   335  	{
   336  		val: struct {
   337  			X *[]uint64
   338  		}{},
   339  		output: "C1C0",
   340  	},
   341  	{
   342  		val: struct {
   343  			X *[]uint64 `rlp:"nilString"`
   344  		}{},
   345  		output: "C180",
   346  	},
   347  
   348  	// interfaces
   349  	{val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct
   350  
   351  	// Encoder
   352  	{val: (*testEncoder)(nil), output: "C0"},
   353  	{val: &testEncoder{}, output: "00010001000100010001"},
   354  	{val: &testEncoder{errors.New("test error")}, error: "test error"},
   355  	{val: struct{ E testEncoderValueMethod }{}, output: "C3FAFEF0"},
   356  	{val: struct{ E *testEncoderValueMethod }{}, output: "C1C0"},
   357  
   358  	// Verify that the Encoder interface works for unsupported types like func().
   359  	{val: undecodableEncoder(func() {}), output: "F5F5F5"},
   360  
   361  	// Verify that pointer method testEncoder.EncodeRLP is called for
   362  	// addressable non-pointer values.
   363  	{val: &struct{ TE testEncoder }{testEncoder{}}, output: "CA00010001000100010001"},
   364  	{val: &struct{ TE testEncoder }{testEncoder{errors.New("test error")}}, error: "test error"},
   365  
   366  	// Verify the error for non-addressable non-pointer Encoder.
   367  	{val: testEncoder{}, error: "rlp: unadressable value of type rlp.testEncoder, EncodeRLP is pointer method"},
   368  
   369  	// Verify Encoder takes precedence over []byte.
   370  	{val: []byteEncoder{0, 1, 2, 3, 4}, output: "C5C0C0C0C0C0"},
   371  }
   372  
   373  func runEncTests(t *testing.T, f func(val interface{}) ([]byte, error)) {
   374  	for i, test := range encTests {
   375  		output, err := f(test.val)
   376  		if err != nil && test.error == "" {
   377  			t.Errorf("test %d: unexpected error: %v\nvalue %#v\ntype %T",
   378  				i, err, test.val, test.val)
   379  			continue
   380  		}
   381  		if test.error != "" && fmt.Sprint(err) != test.error {
   382  			t.Errorf("test %d: error mismatch\ngot   %v\nwant  %v\nvalue %#v\ntype  %T",
   383  				i, err, test.error, test.val, test.val)
   384  			continue
   385  		}
   386  		if err == nil && !bytes.Equal(output, unhex(test.output)) {
   387  			t.Errorf("test %d: output mismatch:\ngot   %X\nwant  %s\nvalue %#v\ntype  %T",
   388  				i, output, test.output, test.val, test.val)
   389  		}
   390  	}
   391  }
   392  
   393  func TestEncode(t *testing.T) {
   394  	runEncTests(t, func(val interface{}) ([]byte, error) {
   395  		b := new(bytes.Buffer)
   396  		err := Encode(b, val)
   397  		return b.Bytes(), err
   398  	})
   399  }
   400  
   401  func TestEncodeToBytes(t *testing.T) {
   402  	runEncTests(t, EncodeToBytes)
   403  }
   404  
   405  func TestEncodeAppendToBytes(t *testing.T) {
   406  	buffer := make([]byte, 20)
   407  	runEncTests(t, func(val interface{}) ([]byte, error) {
   408  		w := NewEncoderBuffer(nil)
   409  		defer w.Flush()
   410  
   411  		err := Encode(w, val)
   412  		if err != nil {
   413  			return nil, err
   414  		}
   415  		output := w.AppendToBytes(buffer[:0])
   416  		return output, nil
   417  	})
   418  }
   419  
   420  func TestEncodeToReader(t *testing.T) {
   421  	runEncTests(t, func(val interface{}) ([]byte, error) {
   422  		_, r, err := EncodeToReader(val)
   423  		if err != nil {
   424  			return nil, err
   425  		}
   426  		return io.ReadAll(r)
   427  	})
   428  }
   429  
   430  func TestEncodeToReaderPiecewise(t *testing.T) {
   431  	runEncTests(t, func(val interface{}) ([]byte, error) {
   432  		size, r, err := EncodeToReader(val)
   433  		if err != nil {
   434  			return nil, err
   435  		}
   436  
   437  		// read output piecewise
   438  		output := make([]byte, size)
   439  		for start, end := 0, 0; start < size; start = end {
   440  			if remaining := size - start; remaining < 3 {
   441  				end += remaining
   442  			} else {
   443  				end = start + 3
   444  			}
   445  			n, err := r.Read(output[start:end])
   446  			end = start + n
   447  			if err == io.EOF {
   448  				break
   449  			} else if err != nil {
   450  				return nil, err
   451  			}
   452  		}
   453  		return output, nil
   454  	})
   455  }
   456  
   457  // This is a regression test verifying that encReader
   458  // returns its encbuf to the pool only once.
   459  func TestEncodeToReaderReturnToPool(t *testing.T) {
   460  	buf := make([]byte, 50)
   461  	wg := new(sync.WaitGroup)
   462  	for i := 0; i < 5; i++ {
   463  		wg.Add(1)
   464  		go func() {
   465  			for i := 0; i < 1000; i++ {
   466  				_, r, _ := EncodeToReader("foo")
   467  				io.ReadAll(r)
   468  				r.Read(buf)
   469  				r.Read(buf)
   470  				r.Read(buf)
   471  				r.Read(buf)
   472  			}
   473  			wg.Done()
   474  		}()
   475  	}
   476  	wg.Wait()
   477  }
   478  
   479  var sink interface{}
   480  
   481  func BenchmarkIntsize(b *testing.B) {
   482  	for i := 0; i < b.N; i++ {
   483  		sink = intsize(0x12345678)
   484  	}
   485  }
   486  
   487  func BenchmarkPutint(b *testing.B) {
   488  	buf := make([]byte, 8)
   489  	for i := 0; i < b.N; i++ {
   490  		putint(buf, 0x12345678)
   491  		sink = buf
   492  	}
   493  }
   494  
   495  func BenchmarkEncodeBigInts(b *testing.B) {
   496  	ints := make([]*big.Int, 200)
   497  	for i := range ints {
   498  		ints[i] = math.BigPow(2, int64(i))
   499  	}
   500  	out := bytes.NewBuffer(make([]byte, 0, 4096))
   501  	b.ResetTimer()
   502  	b.ReportAllocs()
   503  
   504  	for i := 0; i < b.N; i++ {
   505  		out.Reset()
   506  		if err := Encode(out, ints); err != nil {
   507  			b.Fatal(err)
   508  		}
   509  	}
   510  }
   511  
   512  func BenchmarkEncodeConcurrentInterface(b *testing.B) {
   513  	type struct1 struct {
   514  		A string
   515  		B *big.Int
   516  		C [20]byte
   517  	}
   518  	value := []interface{}{
   519  		uint(999),
   520  		&struct1{A: "hello", B: big.NewInt(0xFFFFFFFF)},
   521  		[10]byte{1, 2, 3, 4, 5, 6},
   522  		[]string{"yeah", "yeah", "yeah"},
   523  	}
   524  
   525  	var wg sync.WaitGroup
   526  	for cpu := 0; cpu < runtime.NumCPU(); cpu++ {
   527  		wg.Add(1)
   528  		go func() {
   529  			defer wg.Done()
   530  
   531  			var buffer bytes.Buffer
   532  			for i := 0; i < b.N; i++ {
   533  				buffer.Reset()
   534  				err := Encode(&buffer, value)
   535  				if err != nil {
   536  					panic(err)
   537  				}
   538  			}
   539  		}()
   540  	}
   541  	wg.Wait()
   542  }
   543  
   544  type byteArrayStruct struct {
   545  	A [20]byte
   546  	B [32]byte
   547  	C [32]byte
   548  }
   549  
   550  func BenchmarkEncodeByteArrayStruct(b *testing.B) {
   551  	var out bytes.Buffer
   552  	var value byteArrayStruct
   553  
   554  	b.ReportAllocs()
   555  	for i := 0; i < b.N; i++ {
   556  		out.Reset()
   557  		if err := Encode(&out, &value); err != nil {
   558  			b.Fatal(err)
   559  		}
   560  	}
   561  }
   562  
   563  type structSliceElem struct {
   564  	X uint64
   565  	Y uint64
   566  	Z uint64
   567  }
   568  
   569  type structPtrSlice []*structSliceElem
   570  
   571  func BenchmarkEncodeStructPtrSlice(b *testing.B) {
   572  	var out bytes.Buffer
   573  	var value = structPtrSlice{
   574  		&structSliceElem{1, 1, 1},
   575  		&structSliceElem{2, 2, 2},
   576  		&structSliceElem{3, 3, 3},
   577  		&structSliceElem{5, 5, 5},
   578  		&structSliceElem{6, 6, 6},
   579  		&structSliceElem{7, 7, 7},
   580  	}
   581  
   582  	b.ReportAllocs()
   583  	for i := 0; i < b.N; i++ {
   584  		out.Reset()
   585  		if err := Encode(&out, &value); err != nil {
   586  			b.Fatal(err)
   587  		}
   588  	}
   589  }