From e96cd34e362410ee848da4c634883aead24af9ac Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Tue, 17 Sep 2024 18:48:11 +0700 Subject: [PATCH] rlp.Decode: alloc-free reader (#12013) it's 15% of allocs of `blockReader.GetBlockWithSenders` --- rlp/decode.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/rlp/decode.go b/rlp/decode.go index 775cb875178..1b27c1766f0 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -121,7 +121,7 @@ func Decode(r io.Reader, val interface{}) error { // DecodeBytes parses RLP data from b into val. Please see package-level documentation for // the decoding rules. The input must contain exactly one value and no trailing data. func DecodeBytes(b []byte, val interface{}) error { - r := bytes.NewReader(b) + r := (*sliceReader)(&b) stream, ok := streamPool.Get().(*Stream) if !ok { @@ -133,7 +133,7 @@ func DecodeBytes(b []byte, val interface{}) error { if err := stream.Decode(val); err != nil { return err } - if r.Len() > 0 { + if len(b) > 0 { return ErrMoreThanOneValue } return nil @@ -1131,3 +1131,23 @@ func (s *Stream) willRead(n uint64) error { } return nil } + +type sliceReader []byte + +func (sr *sliceReader) Read(b []byte) (int, error) { + if len(*sr) == 0 { + return 0, io.EOF + } + n := copy(b, *sr) + *sr = (*sr)[n:] + return n, nil +} + +func (sr *sliceReader) ReadByte() (byte, error) { + if len(*sr) == 0 { + return 0, io.EOF + } + b := (*sr)[0] + *sr = (*sr)[1:] + return b, nil +}