github.com/klaytn/klaytn@v1.12.1/rlp/encode_test.go (about)

     1  // Modifications Copyright 2022 The klaytn Authors
     2  // Copyright 2014 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from rlp/encode_test.go(2022/05/19)
    19  // Modified and improved for the klaytn development.
    20  
    21  package rlp
    22  
    23  import (
    24  	"bytes"
    25  	"errors"
    26  	"fmt"
    27  	"io"
    28  	"math/big"
    29  	"runtime"
    30  	"sync"
    31  	"testing"
    32  
    33  	"github.com/klaytn/klaytn/common/math"
    34  )
    35  
    36  type testEncoder struct {
    37  	err error
    38  }
    39  
    40  func (e *testEncoder) EncodeRLP(w io.Writer) error {
    41  	if e == nil {
    42  		panic("EncodeRLP called on nil value")
    43  	}
    44  	if e.err != nil {
    45  		return e.err
    46  	}
    47  	w.Write([]byte{0, 1, 0, 1, 0, 1, 0, 1, 0, 1})
    48  	return nil
    49  }
    50  
    51  type testEncoderValueMethod struct{}
    52  
    53  func (e testEncoderValueMethod) EncodeRLP(w io.Writer) error {
    54  	w.Write([]byte{0xFA, 0xFE, 0xF0})
    55  	return nil
    56  }
    57  
    58  type byteEncoder byte
    59  
    60  func (e byteEncoder) EncodeRLP(w io.Writer) error {
    61  	w.Write(EmptyList)
    62  	return nil
    63  }
    64  
    65  type undecodableEncoder func()
    66  
    67  func (f undecodableEncoder) EncodeRLP(w io.Writer) error {
    68  	w.Write([]byte{0xF5, 0xF5, 0xF5})
    69  	return nil
    70  }
    71  
    72  type encodableReader struct {
    73  	A, B uint
    74  }
    75  
    76  func (e *encodableReader) Read(b []byte) (int, error) {
    77  	panic("called")
    78  }
    79  
    80  type namedByteType byte
    81  
    82  var (
    83  	_ = Encoder(&testEncoder{})
    84  	_ = Encoder(byteEncoder(0))
    85  
    86  	reader io.Reader = &encodableReader{1, 2}
    87  )
    88  
    89  type encTest struct {
    90  	val           interface{}
    91  	output, error string
    92  }
    93  
    94  var encTests = []encTest{
    95  	// booleans
    96  	{val: true, output: "01"},
    97  	{val: false, output: "80"},
    98  
    99  	// integers
   100  	{val: uint32(0), output: "80"},
   101  	{val: uint32(127), output: "7F"},
   102  	{val: uint32(128), output: "8180"},
   103  	{val: uint32(256), output: "820100"},
   104  	{val: uint32(1024), output: "820400"},
   105  	{val: uint32(0xFFFFFF), output: "83FFFFFF"},
   106  	{val: uint32(0xFFFFFFFF), output: "84FFFFFFFF"},
   107  	{val: uint64(0xFFFFFFFF), output: "84FFFFFFFF"},
   108  	{val: uint64(0xFFFFFFFFFF), output: "85FFFFFFFFFF"},
   109  	{val: uint64(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"},
   110  	{val: uint64(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"},
   111  	{val: uint64(0xFFFFFFFFFFFFFFFF), output: "88FFFFFFFFFFFFFFFF"},
   112  
   113  	// big integers (should match uint for small values)
   114  	{val: big.NewInt(0), output: "80"},
   115  	{val: big.NewInt(1), output: "01"},
   116  	{val: big.NewInt(127), output: "7F"},
   117  	{val: big.NewInt(128), output: "8180"},
   118  	{val: big.NewInt(256), output: "820100"},
   119  	{val: big.NewInt(1024), output: "820400"},
   120  	{val: big.NewInt(0xFFFFFF), output: "83FFFFFF"},
   121  	{val: big.NewInt(0xFFFFFFFF), output: "84FFFFFFFF"},
   122  	{val: big.NewInt(0xFFFFFFFFFF), output: "85FFFFFFFFFF"},
   123  	{val: big.NewInt(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"},
   124  	{val: big.NewInt(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"},
   125  	{
   126  		val:    big.NewInt(0).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")),
   127  		output: "8F102030405060708090A0B0C0D0E0F2",
   128  	},
   129  	{
   130  		val:    big.NewInt(0).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")),
   131  		output: "9C0100020003000400050006000700080009000A000B000C000D000E01",
   132  	},
   133  	{
   134  		val:    big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")),
   135  		output: "A1010000000000000000000000000000000000000000000000000000000000000000",
   136  	},
   137  	{
   138  		val:    veryBigInt,
   139  		output: "89FFFFFFFFFFFFFFFFFF",
   140  	},
   141  	{
   142  		val:    veryVeryBigInt,
   143  		output: "B848FFFFFFFFFFFFFFFFF800000000000000001BFFFFFFFFFFFFFFFFC8000000000000000045FFFFFFFFFFFFFFFFC800000000000000001BFFFFFFFFFFFFFFFFF8000000000000000001",
   144  	},
   145  
   146  	// non-pointer big.Int
   147  	{val: *big.NewInt(0), output: "80"},
   148  	{val: *big.NewInt(0xFFFFFF), output: "83FFFFFF"},
   149  
   150  	// negative ints are not supported
   151  	{val: big.NewInt(-1), error: "rlp: cannot encode negative big.Int"},
   152  	{val: *big.NewInt(-1), error: "rlp: cannot encode negative big.Int"},
   153  
   154  	// byte arrays
   155  	{val: [0]byte{}, output: "80"},
   156  	{val: [1]byte{0}, output: "00"},
   157  	{val: [1]byte{1}, output: "01"},
   158  	{val: [1]byte{0x7F}, output: "7F"},
   159  	{val: [1]byte{0x80}, output: "8180"},
   160  	{val: [1]byte{0xFF}, output: "81FF"},
   161  	{val: [3]byte{1, 2, 3}, output: "83010203"},
   162  	{val: [57]byte{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
   163  
   164  	// named byte type arrays
   165  	{val: [0]namedByteType{}, output: "80"},
   166  	{val: [1]namedByteType{0}, output: "00"},
   167  	{val: [1]namedByteType{1}, output: "01"},
   168  	{val: [1]namedByteType{0x7F}, output: "7F"},
   169  	{val: [1]namedByteType{0x80}, output: "8180"},
   170  	{val: [1]namedByteType{0xFF}, output: "81FF"},
   171  	{val: [3]namedByteType{1, 2, 3}, output: "83010203"},
   172  	{val: [57]namedByteType{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
   173  
   174  	// byte slices
   175  	{val: []byte{}, output: "80"},
   176  	{val: []byte{0}, output: "00"},
   177  	{val: []byte{0x7E}, output: "7E"},
   178  	{val: []byte{0x7F}, output: "7F"},
   179  	{val: []byte{0x80}, output: "8180"},
   180  	{val: []byte{1, 2, 3}, output: "83010203"},
   181  
   182  	// named byte type slices
   183  	{val: []namedByteType{}, output: "80"},
   184  	{val: []namedByteType{0}, output: "00"},
   185  	{val: []namedByteType{0x7E}, output: "7E"},
   186  	{val: []namedByteType{0x7F}, output: "7F"},
   187  	{val: []namedByteType{0x80}, output: "8180"},
   188  	{val: []namedByteType{1, 2, 3}, output: "83010203"},
   189  
   190  	// strings
   191  	{val: "", output: "80"},
   192  	{val: "\x7E", output: "7E"},
   193  	{val: "\x7F", output: "7F"},
   194  	{val: "\x80", output: "8180"},
   195  	{val: "dog", output: "83646F67"},
   196  	{
   197  		val:    "Lorem ipsum dolor sit amet, consectetur adipisicing eli",
   198  		output: "B74C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C69",
   199  	},
   200  	{
   201  		val:    "Lorem ipsum dolor sit amet, consectetur adipisicing elit",
   202  		output: "B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974",
   203  	},
   204  	{
   205  		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",
   206  		output: "B904004C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742E20437572616269747572206D6175726973206D61676E612C20737573636970697420736564207665686963756C61206E6F6E2C20696163756C697320666175636962757320746F72746F722E2050726F696E20737573636970697420756C74726963696573206D616C6573756164612E204475697320746F72746F7220656C69742C2064696374756D2071756973207472697374697175652065752C20756C7472696365732061742072697375732E204D6F72626920612065737420696D70657264696574206D6920756C6C616D636F7270657220616C6971756574207375736369706974206E6563206C6F72656D2E2041656E65616E2071756973206C656F206D6F6C6C69732C2076756C70757461746520656C6974207661726975732C20636F6E73657175617420656E696D2E204E756C6C6120756C74726963657320747572706973206A7573746F2C20657420706F73756572652075726E6120636F6E7365637465747572206E65632E2050726F696E206E6F6E20636F6E76616C6C6973206D657475732E20446F6E65632074656D706F7220697073756D20696E206D617572697320636F6E67756520736F6C6C696369747564696E2E20566573746962756C756D20616E746520697073756D207072696D697320696E206661756369627573206F726369206C756374757320657420756C74726963657320706F737565726520637562696C69612043757261653B2053757370656E646973736520636F6E76616C6C69732073656D2076656C206D617373612066617563696275732C2065676574206C6163696E6961206C616375732074656D706F722E204E756C6C61207175697320756C747269636965732070757275732E2050726F696E20617563746F722072686F6E637573206E69626820636F6E64696D656E74756D206D6F6C6C69732E20416C697175616D20636F6E73657175617420656E696D206174206D65747573206C75637475732C206120656C656966656E6420707572757320656765737461732E20437572616269747572206174206E696268206D657475732E204E616D20626962656E64756D2C206E6571756520617420617563746F72207472697374697175652C206C6F72656D206C696265726F20616C697175657420617263752C206E6F6E20696E74657264756D2074656C6C7573206C65637475732073697420616D65742065726F732E20437261732072686F6E6375732C206D65747573206163206F726E617265206375727375732C20646F6C6F72206A7573746F20756C747269636573206D657475732C20617420756C6C616D636F7270657220766F6C7574706174",
   207  	},
   208  
   209  	// slices
   210  	{val: []uint{}, output: "C0"},
   211  	{val: []uint{1, 2, 3}, output: "C3010203"},
   212  	{
   213  		// [ [], [[]], [ [], [[]] ] ]
   214  		val:    []interface{}{[]interface{}{}, [][]interface{}{{}}, []interface{}{[]interface{}{}, [][]interface{}{{}}}},
   215  		output: "C7C0C1C0C3C0C1C0",
   216  	},
   217  	{
   218  		val:    []string{"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo"},
   219  		output: "F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F",
   220  	},
   221  	{
   222  		val:    []interface{}{uint(1), uint(0xFFFFFF), []interface{}{[]uint{4, 5, 5}}, "abc"},
   223  		output: "CE0183FFFFFFC4C304050583616263",
   224  	},
   225  	{
   226  		val: [][]string{
   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  			{"asdf", "qwer", "zxcv"},
   256  			{"asdf", "qwer", "zxcv"},
   257  			{"asdf", "qwer", "zxcv"},
   258  			{"asdf", "qwer", "zxcv"},
   259  		},
   260  		output: "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376",
   261  	},
   262  
   263  	// RawValue
   264  	{val: RawValue(unhex("01")), output: "01"},
   265  	{val: RawValue(unhex("82FFFF")), output: "82FFFF"},
   266  	{val: []RawValue{unhex("01"), unhex("02")}, output: "C20102"},
   267  
   268  	// structs
   269  	{val: simplestruct{}, output: "C28080"},
   270  	{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},
   271  	{val: &recstruct{5, nil}, output: "C205C0"},
   272  	{val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"},
   273  	{val: &intField{X: 3}, error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)"},
   274  
   275  	// struct tag "-"
   276  	{val: &ignoredField{A: 1, B: 2, C: 3}, output: "C20103"},
   277  
   278  	// struct tag "tail"
   279  	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"},
   280  	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
   281  	{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
   282  	{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
   283  
   284  	// struct tag "optional"
   285  	{val: &optionalFields{}, output: "C180"},
   286  	{val: &optionalFields{A: 1}, output: "C101"},
   287  	{val: &optionalFields{A: 1, B: 2}, output: "C20102"},
   288  	{val: &optionalFields{A: 1, B: 2, C: 3}, output: "C3010203"},
   289  	{val: &optionalFields{A: 1, B: 0, C: 3}, output: "C3018003"},
   290  	{val: &optionalAndTailField{A: 1}, output: "C101"},
   291  	{val: &optionalAndTailField{A: 1, B: 2}, output: "C20102"},
   292  	{val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
   293  	{val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
   294  	{val: &optionalBigIntField{A: 1}, output: "C101"},
   295  	{val: &optionalPtrField{A: 1}, output: "C101"},
   296  	{val: &optionalPtrFieldNil{A: 1}, output: "C101"},
   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  	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  }