github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/utils/cser/read_writer.go (about) 1 package cser 2 3 import ( 4 "errors" 5 "math/big" 6 7 "github.com/unicornultrafoundation/go-u2u/utils/bits" 8 "github.com/unicornultrafoundation/go-u2u/utils/fast" 9 ) 10 11 var ( 12 ErrNonCanonicalEncoding = errors.New("non canonical encoding") 13 ErrMalformedEncoding = errors.New("malformed encoding") 14 ErrTooLargeAlloc = errors.New("too large allocation") 15 ) 16 17 const MaxAlloc = 100 * 1024 18 19 type Writer struct { 20 BitsW *bits.Writer 21 BytesW *fast.Writer 22 } 23 24 type Reader struct { 25 BitsR *bits.Reader 26 BytesR *fast.Reader 27 } 28 29 func NewWriter() *Writer { 30 bbits := &bits.Array{Bytes: make([]byte, 0, 32)} 31 bbytes := make([]byte, 0, 200) 32 return &Writer{ 33 BitsW: bits.NewWriter(bbits), 34 BytesW: fast.NewWriter(bbytes), 35 } 36 } 37 38 func writeUint64Compact(bytesW *fast.Writer, v uint64) { 39 for i := 0; ; i++ { 40 chunk := v & 0b01111111 41 v = v >> 7 42 if v == 0 { 43 // stop flag 44 chunk |= 0b10000000 45 } 46 bytesW.WriteByte(byte(chunk)) 47 if v == 0 { 48 break 49 } 50 } 51 return 52 } 53 54 func readUint64Compact(bytesR *fast.Reader) uint64 { 55 v := uint64(0) 56 stop := false 57 for i := 0; !stop; i++ { 58 chunk := uint64(bytesR.ReadByte()) 59 stop = (chunk & 0b10000000) != 0 60 word := chunk & 0b01111111 61 v |= word << (i * 7) 62 // last byte cannot be zero 63 if i > 0 && stop && word == 0 { 64 panic(ErrNonCanonicalEncoding) 65 } 66 } 67 68 return v 69 } 70 71 func writeUint64BitCompact(bytesW *fast.Writer, v uint64, minSize int) (size int) { 72 for size < minSize || v != 0 { 73 bytesW.WriteByte(byte(v)) 74 size++ 75 v = v >> 8 76 } 77 return 78 } 79 80 func readUint64BitCompact(bytesR *fast.Reader, size int) uint64 { 81 var ( 82 v uint64 83 last byte 84 ) 85 buf := bytesR.Read(size) 86 for i, b := range buf { 87 v |= uint64(b) << uint(8*i) 88 last = b 89 } 90 91 if size > 1 && last == 0 { 92 panic(ErrNonCanonicalEncoding) 93 } 94 95 return v 96 } 97 98 func (r *Reader) U8() uint8 { 99 return r.BytesR.ReadByte() 100 } 101 102 func (w *Writer) U8(v uint8) { 103 w.BytesW.WriteByte(v) 104 } 105 106 func (r *Reader) readU64_bits(minSize int, bitsForSize int) uint64 { 107 size := r.BitsR.Read(bitsForSize) 108 size += uint(minSize) 109 return readUint64BitCompact(r.BytesR, int(size)) 110 } 111 112 func (w *Writer) writeU64_bits(minSize int, bitsForSize int, v uint64) { 113 size := writeUint64BitCompact(w.BytesW, v, minSize) 114 w.BitsW.Write(bitsForSize, uint(size-minSize)) 115 } 116 117 func (r *Reader) U16() uint16 { 118 v64 := r.readU64_bits(1, 1) 119 return uint16(v64) 120 } 121 122 func (w *Writer) U16(v uint16) { 123 w.writeU64_bits(1, 1, uint64(v)) 124 } 125 126 func (r *Reader) U32() uint32 { 127 v64 := r.readU64_bits(1, 2) 128 return uint32(v64) 129 } 130 131 func (w *Writer) U32(v uint32) { 132 w.writeU64_bits(1, 2, uint64(v)) 133 } 134 135 func (r *Reader) U64() uint64 { 136 return r.readU64_bits(1, 3) 137 } 138 139 func (w *Writer) U64(v uint64) { 140 w.writeU64_bits(1, 3, v) 141 } 142 143 func (r *Reader) VarUint() uint64 { 144 return r.readU64_bits(1, 3) 145 } 146 147 func (w *Writer) VarUint(v uint64) { 148 w.writeU64_bits(1, 3, v) 149 } 150 151 func (r *Reader) I64() int64 { 152 neg := r.Bool() 153 abs := r.U64() 154 if neg && abs == 0 { 155 panic(ErrNonCanonicalEncoding) 156 } 157 if neg { 158 return -int64(abs) 159 } 160 return int64(abs) 161 } 162 163 func (w *Writer) I64(v int64) { 164 w.Bool(v < 0) 165 if v < 0 { 166 w.U64(uint64(-v)) 167 } else { 168 w.U64(uint64(v)) 169 } 170 } 171 172 func (r *Reader) U56() uint64 { 173 return r.readU64_bits(0, 3) 174 } 175 176 func (w *Writer) U56(v uint64) { 177 const max = 1<<(8*7) - 1 178 if v > max { 179 panic("Value too big") 180 } 181 w.writeU64_bits(0, 3, v) 182 } 183 184 func (r *Reader) Bool() bool { 185 u8 := r.BitsR.Read(1) 186 return u8 != 0 187 } 188 189 func (w *Writer) Bool(v bool) { 190 u8 := uint(0) 191 if v { 192 u8 = 1 193 } 194 w.BitsW.Write(1, u8) 195 } 196 197 func (r *Reader) FixedBytes(v []byte) { 198 buf := r.BytesR.Read(len(v)) 199 copy(v, buf) 200 } 201 202 func (w *Writer) FixedBytes(v []byte) { 203 w.BytesW.Write(v) 204 } 205 206 func (r *Reader) SliceBytes(maxLen int) []byte { 207 // read slice size 208 size := r.U56() 209 if size > uint64(maxLen) { 210 panic(ErrTooLargeAlloc) 211 } 212 buf := make([]byte, size) 213 // read slice content 214 r.FixedBytes(buf) 215 return buf 216 } 217 218 func (w *Writer) SliceBytes(v []byte) { 219 // write slice size 220 w.U56(uint64(len(v))) 221 // write slice content 222 w.FixedBytes(v) 223 } 224 225 // PaddedBytes returns a slice with length of the slice is at least n bytes. 226 func PaddedBytes(b []byte, n int) []byte { 227 if len(b) >= n { 228 return b 229 } 230 padding := make([]byte, n-len(b)) 231 return append(padding, b...) 232 } 233 234 func (w *Writer) BigInt(v *big.Int) { 235 // serialize as an ordinary slice 236 bigBytes := []byte{} 237 if v.Sign() != 0 { 238 bigBytes = v.Bytes() 239 } 240 w.SliceBytes(bigBytes) 241 } 242 243 func (r *Reader) BigInt() *big.Int { 244 // deserialize as an ordinary slice 245 buf := r.SliceBytes(512) 246 if len(buf) == 0 { 247 return new(big.Int) 248 } 249 return new(big.Int).SetBytes(buf) 250 }