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

     1  // Copyright 2022 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  	"io"
    21  	"math/big"
    22  	"reflect"
    23  	"sync"
    24  )
    25  
    26  type encBuffer struct {
    27  	str     []byte     // string data, contains everything except list headers
    28  	lheads  []listhead // all list headers
    29  	lhsize  int        // sum of sizes of all encoded list headers
    30  	sizebuf [9]byte    // auxiliary buffer for uint encoding
    31  }
    32  
    33  // The global encBuffer pool.
    34  var encBufferPool = sync.Pool{
    35  	New: func() interface{} { return new(encBuffer) },
    36  }
    37  
    38  func getEncBuffer() *encBuffer {
    39  	buf := encBufferPool.Get().(*encBuffer)
    40  	buf.reset()
    41  	return buf
    42  }
    43  
    44  func (buf *encBuffer) reset() {
    45  	buf.lhsize = 0
    46  	buf.str = buf.str[:0]
    47  	buf.lheads = buf.lheads[:0]
    48  }
    49  
    50  // size returns the length of the encoded data.
    51  func (buf *encBuffer) size() int {
    52  	return len(buf.str) + buf.lhsize
    53  }
    54  
    55  // makeBytes creates the encoder output.
    56  func (w *encBuffer) makeBytes() []byte {
    57  	out := make([]byte, w.size())
    58  	w.copyTo(out)
    59  	return out
    60  }
    61  
    62  func (w *encBuffer) copyTo(dst []byte) {
    63  	strpos := 0
    64  	pos := 0
    65  	for _, head := range w.lheads {
    66  		// write string data before header
    67  		n := copy(dst[pos:], w.str[strpos:head.offset])
    68  		pos += n
    69  		strpos += n
    70  		// write the header
    71  		enc := head.encode(dst[pos:])
    72  		pos += len(enc)
    73  	}
    74  	// copy string data after the last list header
    75  	copy(dst[pos:], w.str[strpos:])
    76  }
    77  
    78  // writeTo writes the encoder output to w.
    79  func (buf *encBuffer) writeTo(w io.Writer) (err error) {
    80  	strpos := 0
    81  	for _, head := range buf.lheads {
    82  		// write string data before header
    83  		if head.offset-strpos > 0 {
    84  			n, err := w.Write(buf.str[strpos:head.offset])
    85  			strpos += n
    86  			if err != nil {
    87  				return err
    88  			}
    89  		}
    90  		// write the header
    91  		enc := head.encode(buf.sizebuf[:])
    92  		if _, err = w.Write(enc); err != nil {
    93  			return err
    94  		}
    95  	}
    96  	if strpos < len(buf.str) {
    97  		// write string data after the last list header
    98  		_, err = w.Write(buf.str[strpos:])
    99  	}
   100  	return err
   101  }
   102  
   103  // Write implements io.Writer and appends b directly to the output.
   104  func (buf *encBuffer) Write(b []byte) (int, error) {
   105  	buf.str = append(buf.str, b...)
   106  	return len(b), nil
   107  }
   108  
   109  // writeBool writes b as the integer 0 (false) or 1 (true).
   110  func (buf *encBuffer) writeBool(b bool) {
   111  	if b {
   112  		buf.str = append(buf.str, 0x01)
   113  	} else {
   114  		buf.str = append(buf.str, 0x80)
   115  	}
   116  }
   117  
   118  func (buf *encBuffer) writeUint64(i uint64) {
   119  	if i == 0 {
   120  		buf.str = append(buf.str, 0x80)
   121  	} else if i < 128 {
   122  		// fits single byte
   123  		buf.str = append(buf.str, byte(i))
   124  	} else {
   125  		s := putint(buf.sizebuf[1:], i)
   126  		buf.sizebuf[0] = 0x80 + byte(s)
   127  		buf.str = append(buf.str, buf.sizebuf[:s+1]...)
   128  	}
   129  }
   130  
   131  func (buf *encBuffer) writeBytes(b []byte) {
   132  	if len(b) == 1 && b[0] <= 0x7F {
   133  		// fits single byte, no string header
   134  		buf.str = append(buf.str, b[0])
   135  	} else {
   136  		buf.encodeStringHeader(len(b))
   137  		buf.str = append(buf.str, b...)
   138  	}
   139  }
   140  
   141  func (buf *encBuffer) writeString(s string) {
   142  	buf.writeBytes([]byte(s))
   143  }
   144  
   145  // wordBytes is the number of bytes in a big.Word
   146  const wordBytes = (32 << (uint64(^big.Word(0)) >> 63)) / 8
   147  
   148  // writeBigInt writes i as an integer.
   149  func (w *encBuffer) writeBigInt(i *big.Int) {
   150  	bitlen := i.BitLen()
   151  	if bitlen <= 64 {
   152  		w.writeUint64(i.Uint64())
   153  		return
   154  	}
   155  	// Integer is larger than 64 bits, encode from i.Bits().
   156  	// The minimal byte length is bitlen rounded up to the next
   157  	// multiple of 8, divided by 8.
   158  	length := ((bitlen + 7) & -8) >> 3
   159  	w.encodeStringHeader(length)
   160  	w.str = append(w.str, make([]byte, length)...)
   161  	index := length
   162  	buf := w.str[len(w.str)-length:]
   163  	for _, d := range i.Bits() {
   164  		for j := 0; j < wordBytes && index > 0; j++ {
   165  			index--
   166  			buf[index] = byte(d)
   167  			d >>= 8
   168  		}
   169  	}
   170  }
   171  
   172  // list adds a new list header to the header stack. It returns the index of the header.
   173  // Call listEnd with this index after encoding the content of the list.
   174  func (buf *encBuffer) list() int {
   175  	buf.lheads = append(buf.lheads, listhead{offset: len(buf.str), size: buf.lhsize})
   176  	return len(buf.lheads) - 1
   177  }
   178  
   179  func (buf *encBuffer) listEnd(index int) {
   180  	lh := &buf.lheads[index]
   181  	lh.size = buf.size() - lh.offset - lh.size
   182  	if lh.size < 56 {
   183  		buf.lhsize++ // length encoded into kind tag
   184  	} else {
   185  		buf.lhsize += 1 + intsize(uint64(lh.size))
   186  	}
   187  }
   188  
   189  func (buf *encBuffer) encode(val interface{}) error {
   190  	rval := reflect.ValueOf(val)
   191  	writer, err := cachedWriter(rval.Type())
   192  	if err != nil {
   193  		return err
   194  	}
   195  	return writer(rval, buf)
   196  }
   197  
   198  func (buf *encBuffer) encodeStringHeader(size int) {
   199  	if size < 56 {
   200  		buf.str = append(buf.str, 0x80+byte(size))
   201  	} else {
   202  		sizesize := putint(buf.sizebuf[1:], uint64(size))
   203  		buf.sizebuf[0] = 0xB7 + byte(sizesize)
   204  		buf.str = append(buf.str, buf.sizebuf[:sizesize+1]...)
   205  	}
   206  }
   207  
   208  // encReader is the io.Reader returned by EncodeToReader.
   209  // It releases its encbuf at EOF.
   210  type encReader struct {
   211  	buf    *encBuffer // the buffer we're reading from. this is nil when we're at EOF.
   212  	lhpos  int        // index of list header that we're reading
   213  	strpos int        // current position in string buffer
   214  	piece  []byte     // next piece to be read
   215  }
   216  
   217  func (r *encReader) Read(b []byte) (n int, err error) {
   218  	for {
   219  		if r.piece = r.next(); r.piece == nil {
   220  			// Put the encode buffer back into the pool at EOF when it
   221  			// is first encountered. Subsequent calls still return EOF
   222  			// as the error but the buffer is no longer valid.
   223  			if r.buf != nil {
   224  				encBufferPool.Put(r.buf)
   225  				r.buf = nil
   226  			}
   227  			return n, io.EOF
   228  		}
   229  		nn := copy(b[n:], r.piece)
   230  		n += nn
   231  		if nn < len(r.piece) {
   232  			// piece didn't fit, see you next time.
   233  			r.piece = r.piece[nn:]
   234  			return n, nil
   235  		}
   236  		r.piece = nil
   237  	}
   238  }
   239  
   240  // next returns the next piece of data to be read.
   241  // it returns nil at EOF.
   242  func (r *encReader) next() []byte {
   243  	switch {
   244  	case r.buf == nil:
   245  		return nil
   246  
   247  	case r.piece != nil:
   248  		// There is still data available for reading.
   249  		return r.piece
   250  
   251  	case r.lhpos < len(r.buf.lheads):
   252  		// We're before the last list header.
   253  		head := r.buf.lheads[r.lhpos]
   254  		sizebefore := head.offset - r.strpos
   255  		if sizebefore > 0 {
   256  			// String data before header.
   257  			p := r.buf.str[r.strpos:head.offset]
   258  			r.strpos += sizebefore
   259  			return p
   260  		}
   261  		r.lhpos++
   262  		return head.encode(r.buf.sizebuf[:])
   263  
   264  	case r.strpos < len(r.buf.str):
   265  		// String data at the end, after all list headers.
   266  		p := r.buf.str[r.strpos:]
   267  		r.strpos = len(r.buf.str)
   268  		return p
   269  
   270  	default:
   271  		return nil
   272  	}
   273  }
   274  
   275  func encBufferFromWriter(w io.Writer) *encBuffer {
   276  	switch w := w.(type) {
   277  	case EncoderBuffer:
   278  		return w.buf
   279  	case *EncoderBuffer:
   280  		return w.buf
   281  	case *encBuffer:
   282  		return w
   283  	default:
   284  		return nil
   285  	}
   286  }
   287  
   288  // EncoderBuffer is a buffer for incremental encoding.
   289  //
   290  // The zero value is NOT ready for use. To get a usable buffer,
   291  // create it using NewEncoderBuffer or call Reset.
   292  type EncoderBuffer struct {
   293  	buf *encBuffer
   294  	dst io.Writer
   295  
   296  	ownBuffer bool
   297  }
   298  
   299  // NewEncoderBuffer creates an encoder buffer.
   300  func NewEncoderBuffer(dst io.Writer) EncoderBuffer {
   301  	var w EncoderBuffer
   302  	w.Reset(dst)
   303  	return w
   304  }
   305  
   306  // Reset truncates the buffer and sets the output destination.
   307  func (w *EncoderBuffer) Reset(dst io.Writer) {
   308  	if w.buf != nil && !w.ownBuffer {
   309  		panic("can't Reset derived EncoderBuffer")
   310  	}
   311  
   312  	// If the destination writer has an *encBuffer, use it.
   313  	// Note that w.ownBuffer is left false here.
   314  	if dst != nil {
   315  		if outer := encBufferFromWriter(dst); outer != nil {
   316  			*w = EncoderBuffer{outer, nil, false}
   317  			return
   318  		}
   319  	}
   320  
   321  	// Get a fresh buffer.
   322  	if w.buf == nil {
   323  		w.buf = encBufferPool.Get().(*encBuffer)
   324  		w.ownBuffer = true
   325  	}
   326  	w.buf.reset()
   327  	w.dst = dst
   328  }
   329  
   330  // Flush writes encoded RLP data to the output writer. This can only be called once.
   331  // If you want to re-use the buffer after Flush, you must call Reset.
   332  func (w *EncoderBuffer) Flush() error {
   333  	var err error
   334  	if w.dst != nil {
   335  		err = w.buf.writeTo(w.dst)
   336  	}
   337  	// Release the internal buffer.
   338  	if w.ownBuffer {
   339  		encBufferPool.Put(w.buf)
   340  	}
   341  	*w = EncoderBuffer{}
   342  	return err
   343  }
   344  
   345  // ToBytes returns the encoded bytes.
   346  func (w *EncoderBuffer) ToBytes() []byte {
   347  	return w.buf.makeBytes()
   348  }
   349  
   350  // AppendToBytes appends the encoded bytes to dst.
   351  func (w *EncoderBuffer) AppendToBytes(dst []byte) []byte {
   352  	size := w.buf.size()
   353  	out := append(dst, make([]byte, size)...)
   354  	w.buf.copyTo(out[len(dst):])
   355  	return out
   356  }
   357  
   358  // Write appends b directly to the encoder output.
   359  func (w EncoderBuffer) Write(b []byte) (int, error) {
   360  	return w.buf.Write(b)
   361  }
   362  
   363  // WriteBool writes b as the integer 0 (false) or 1 (true).
   364  func (w EncoderBuffer) WriteBool(b bool) {
   365  	w.buf.writeBool(b)
   366  }
   367  
   368  // WriteUint64 encodes an unsigned integer.
   369  func (w EncoderBuffer) WriteUint64(i uint64) {
   370  	w.buf.writeUint64(i)
   371  }
   372  
   373  // WriteBigInt encodes a big.Int as an RLP string.
   374  // Note: Unlike with Encode, the sign of i is ignored.
   375  func (w EncoderBuffer) WriteBigInt(i *big.Int) {
   376  	w.buf.writeBigInt(i)
   377  }
   378  
   379  // WriteBytes encodes b as an RLP string.
   380  func (w EncoderBuffer) WriteBytes(b []byte) {
   381  	w.buf.writeBytes(b)
   382  }
   383  
   384  // WriteBytes encodes s as an RLP string.
   385  func (w EncoderBuffer) WriteString(s string) {
   386  	w.buf.writeString(s)
   387  }
   388  
   389  // List starts a list. It returns an internal index. Call EndList with
   390  // this index after encoding the content to finish the list.
   391  func (w EncoderBuffer) List() int {
   392  	return w.buf.list()
   393  }
   394  
   395  // ListEnd finishes the given list.
   396  func (w EncoderBuffer) ListEnd(index int) {
   397  	w.buf.listEnd(index)
   398  }