github.com/bcnmy/go-ethereum@v1.10.27/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  
   294  	// nil
   295  	{val: (*uint)(nil), output: "80"},
   296  	{val: (*string)(nil), output: "80"},
   297  	{val: (*[]byte)(nil), output: "80"},
   298  	{val: (*[10]byte)(nil), output: "80"},
   299  	{val: (*big.Int)(nil), output: "80"},
   300  	{val: (*[]string)(nil), output: "C0"},
   301  	{val: (*[10]string)(nil), output: "C0"},
   302  	{val: (*[]interface{})(nil), output: "C0"},
   303  	{val: (*[]struct{ uint })(nil), output: "C0"},
   304  	{val: (*interface{})(nil), output: "C0"},
   305  
   306  	// nil struct fields
   307  	{
   308  		val: struct {
   309  			X *[]byte
   310  		}{},
   311  		output: "C180",
   312  	},
   313  	{
   314  		val: struct {
   315  			X *[2]byte
   316  		}{},
   317  		output: "C180",
   318  	},
   319  	{
   320  		val: struct {
   321  			X *uint64
   322  		}{},
   323  		output: "C180",
   324  	},
   325  	{
   326  		val: struct {
   327  			X *uint64 `rlp:"nilList"`
   328  		}{},
   329  		output: "C1C0",
   330  	},
   331  	{
   332  		val: struct {
   333  			X *[]uint64
   334  		}{},
   335  		output: "C1C0",
   336  	},
   337  	{
   338  		val: struct {
   339  			X *[]uint64 `rlp:"nilString"`
   340  		}{},
   341  		output: "C180",
   342  	},
   343  
   344  	// interfaces
   345  	{val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct
   346  
   347  	// Encoder
   348  	{val: (*testEncoder)(nil), output: "C0"},
   349  	{val: &testEncoder{}, output: "00010001000100010001"},
   350  	{val: &testEncoder{errors.New("test error")}, error: "test error"},
   351  	{val: struct{ E testEncoderValueMethod }{}, output: "C3FAFEF0"},
   352  	{val: struct{ E *testEncoderValueMethod }{}, output: "C1C0"},
   353  
   354  	// Verify that the Encoder interface works for unsupported types like func().
   355  	{val: undecodableEncoder(func() {}), output: "F5F5F5"},
   356  
   357  	// Verify that pointer method testEncoder.EncodeRLP is called for
   358  	// addressable non-pointer values.
   359  	{val: &struct{ TE testEncoder }{testEncoder{}}, output: "CA00010001000100010001"},
   360  	{val: &struct{ TE testEncoder }{testEncoder{errors.New("test error")}}, error: "test error"},
   361  
   362  	// Verify the error for non-addressable non-pointer Encoder.
   363  	{val: testEncoder{}, error: "rlp: unadressable value of type rlp.testEncoder, EncodeRLP is pointer method"},
   364  
   365  	// Verify Encoder takes precedence over []byte.
   366  	{val: []byteEncoder{0, 1, 2, 3, 4}, output: "C5C0C0C0C0C0"},
   367  }
   368  
   369  func runEncTests(t *testing.T, f func(val interface{}) ([]byte, error)) {
   370  	for i, test := range encTests {
   371  		output, err := f(test.val)
   372  		if err != nil && test.error == "" {
   373  			t.Errorf("test %d: unexpected error: %v\nvalue %#v\ntype %T",
   374  				i, err, test.val, test.val)
   375  			continue
   376  		}
   377  		if test.error != "" && fmt.Sprint(err) != test.error {
   378  			t.Errorf("test %d: error mismatch\ngot   %v\nwant  %v\nvalue %#v\ntype  %T",
   379  				i, err, test.error, test.val, test.val)
   380  			continue
   381  		}
   382  		if err == nil && !bytes.Equal(output, unhex(test.output)) {
   383  			t.Errorf("test %d: output mismatch:\ngot   %X\nwant  %s\nvalue %#v\ntype  %T",
   384  				i, output, test.output, test.val, test.val)
   385  		}
   386  	}
   387  }
   388  
   389  func TestEncode(t *testing.T) {
   390  	runEncTests(t, func(val interface{}) ([]byte, error) {
   391  		b := new(bytes.Buffer)
   392  		err := Encode(b, val)
   393  		return b.Bytes(), err
   394  	})
   395  }
   396  
   397  func TestEncodeToBytes(t *testing.T) {
   398  	runEncTests(t, EncodeToBytes)
   399  }
   400  
   401  func TestEncodeAppendToBytes(t *testing.T) {
   402  	buffer := make([]byte, 20)
   403  	runEncTests(t, func(val interface{}) ([]byte, error) {
   404  		w := NewEncoderBuffer(nil)
   405  		defer w.Flush()
   406  
   407  		err := Encode(w, val)
   408  		if err != nil {
   409  			return nil, err
   410  		}
   411  		output := w.AppendToBytes(buffer[:0])
   412  		return output, nil
   413  	})
   414  }
   415  
   416  func TestEncodeToReader(t *testing.T) {
   417  	runEncTests(t, func(val interface{}) ([]byte, error) {
   418  		_, r, err := EncodeToReader(val)
   419  		if err != nil {
   420  			return nil, err
   421  		}
   422  		return io.ReadAll(r)
   423  	})
   424  }
   425  
   426  func TestEncodeToReaderPiecewise(t *testing.T) {
   427  	runEncTests(t, func(val interface{}) ([]byte, error) {
   428  		size, r, err := EncodeToReader(val)
   429  		if err != nil {
   430  			return nil, err
   431  		}
   432  
   433  		// read output piecewise
   434  		output := make([]byte, size)
   435  		for start, end := 0, 0; start < size; start = end {
   436  			if remaining := size - start; remaining < 3 {
   437  				end += remaining
   438  			} else {
   439  				end = start + 3
   440  			}
   441  			n, err := r.Read(output[start:end])
   442  			end = start + n
   443  			if err == io.EOF {
   444  				break
   445  			} else if err != nil {
   446  				return nil, err
   447  			}
   448  		}
   449  		return output, nil
   450  	})
   451  }
   452  
   453  // This is a regression test verifying that encReader
   454  // returns its encbuf to the pool only once.
   455  func TestEncodeToReaderReturnToPool(t *testing.T) {
   456  	buf := make([]byte, 50)
   457  	wg := new(sync.WaitGroup)
   458  	for i := 0; i < 5; i++ {
   459  		wg.Add(1)
   460  		go func() {
   461  			for i := 0; i < 1000; i++ {
   462  				_, r, _ := EncodeToReader("foo")
   463  				io.ReadAll(r)
   464  				r.Read(buf)
   465  				r.Read(buf)
   466  				r.Read(buf)
   467  				r.Read(buf)
   468  			}
   469  			wg.Done()
   470  		}()
   471  	}
   472  	wg.Wait()
   473  }
   474  
   475  var sink interface{}
   476  
   477  func BenchmarkIntsize(b *testing.B) {
   478  	for i := 0; i < b.N; i++ {
   479  		sink = intsize(0x12345678)
   480  	}
   481  }
   482  
   483  func BenchmarkPutint(b *testing.B) {
   484  	buf := make([]byte, 8)
   485  	for i := 0; i < b.N; i++ {
   486  		putint(buf, 0x12345678)
   487  		sink = buf
   488  	}
   489  }
   490  
   491  func BenchmarkEncodeBigInts(b *testing.B) {
   492  	ints := make([]*big.Int, 200)
   493  	for i := range ints {
   494  		ints[i] = math.BigPow(2, int64(i))
   495  	}
   496  	out := bytes.NewBuffer(make([]byte, 0, 4096))
   497  	b.ResetTimer()
   498  	b.ReportAllocs()
   499  
   500  	for i := 0; i < b.N; i++ {
   501  		out.Reset()
   502  		if err := Encode(out, ints); err != nil {
   503  			b.Fatal(err)
   504  		}
   505  	}
   506  }
   507  
   508  func BenchmarkEncodeConcurrentInterface(b *testing.B) {
   509  	type struct1 struct {
   510  		A string
   511  		B *big.Int
   512  		C [20]byte
   513  	}
   514  	value := []interface{}{
   515  		uint(999),
   516  		&struct1{A: "hello", B: big.NewInt(0xFFFFFFFF)},
   517  		[10]byte{1, 2, 3, 4, 5, 6},
   518  		[]string{"yeah", "yeah", "yeah"},
   519  	}
   520  
   521  	var wg sync.WaitGroup
   522  	for cpu := 0; cpu < runtime.NumCPU(); cpu++ {
   523  		wg.Add(1)
   524  		go func() {
   525  			defer wg.Done()
   526  
   527  			var buffer bytes.Buffer
   528  			for i := 0; i < b.N; i++ {
   529  				buffer.Reset()
   530  				err := Encode(&buffer, value)
   531  				if err != nil {
   532  					panic(err)
   533  				}
   534  			}
   535  		}()
   536  	}
   537  	wg.Wait()
   538  }
   539  
   540  type byteArrayStruct struct {
   541  	A [20]byte
   542  	B [32]byte
   543  	C [32]byte
   544  }
   545  
   546  func BenchmarkEncodeByteArrayStruct(b *testing.B) {
   547  	var out bytes.Buffer
   548  	var value byteArrayStruct
   549  
   550  	b.ReportAllocs()
   551  	for i := 0; i < b.N; i++ {
   552  		out.Reset()
   553  		if err := Encode(&out, &value); err != nil {
   554  			b.Fatal(err)
   555  		}
   556  	}
   557  }
   558  
   559  type structSliceElem struct {
   560  	X uint64
   561  	Y uint64
   562  	Z uint64
   563  }
   564  
   565  type structPtrSlice []*structSliceElem
   566  
   567  func BenchmarkEncodeStructPtrSlice(b *testing.B) {
   568  	var out bytes.Buffer
   569  	var value = structPtrSlice{
   570  		&structSliceElem{1, 1, 1},
   571  		&structSliceElem{2, 2, 2},
   572  		&structSliceElem{3, 3, 3},
   573  		&structSliceElem{5, 5, 5},
   574  		&structSliceElem{6, 6, 6},
   575  		&structSliceElem{7, 7, 7},
   576  	}
   577  
   578  	b.ReportAllocs()
   579  	for i := 0; i < b.N; i++ {
   580  		out.Reset()
   581  		if err := Encode(&out, &value); err != nil {
   582  			b.Fatal(err)
   583  		}
   584  	}
   585  }