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 }