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