github.com/gagliardetto/binary@v0.7.9/encoder.go (about) 1 // Copyright 2021 github.com/gagliardetto 2 // This file has been modified by github.com/gagliardetto 3 // 4 // Copyright 2020 dfuse Platform Inc. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package bin 19 20 import ( 21 "encoding/binary" 22 "errors" 23 "fmt" 24 "io" 25 "math" 26 "reflect" 27 28 "go.uber.org/zap" 29 ) 30 31 type Encoder struct { 32 count int 33 34 currentFieldOpt *option 35 encoding Encoding 36 37 output io.Writer 38 } 39 40 func (enc *Encoder) IsBorsh() bool { 41 return enc.encoding.IsBorsh() 42 } 43 44 func (enc *Encoder) IsBin() bool { 45 return enc.encoding.IsBin() 46 } 47 48 func (enc *Encoder) IsCompactU16() bool { 49 return enc.encoding.IsCompactU16() 50 } 51 52 func NewEncoderWithEncoding(writer io.Writer, enc Encoding) *Encoder { 53 if !isValidEncoding(enc) { 54 panic(fmt.Sprintf("provided encoding is not valid: %s", enc)) 55 } 56 return &Encoder{ 57 output: writer, 58 count: 0, 59 encoding: enc, 60 } 61 } 62 63 func NewBinEncoder(writer io.Writer) *Encoder { 64 return NewEncoderWithEncoding(writer, EncodingBin) 65 } 66 67 func NewBorshEncoder(writer io.Writer) *Encoder { 68 return NewEncoderWithEncoding(writer, EncodingBorsh) 69 } 70 71 func NewCompactU16Encoder(writer io.Writer) *Encoder { 72 return NewEncoderWithEncoding(writer, EncodingCompactU16) 73 } 74 75 func (e *Encoder) Encode(v interface{}) (err error) { 76 switch e.encoding { 77 case EncodingBin: 78 return e.encodeBin(reflect.ValueOf(v), nil) 79 case EncodingBorsh: 80 return e.encodeBorsh(reflect.ValueOf(v), nil) 81 case EncodingCompactU16: 82 return e.encodeCompactU16(reflect.ValueOf(v), nil) 83 default: 84 panic(fmt.Errorf("encoding not implemented: %s", e.encoding)) 85 } 86 } 87 88 func (e *Encoder) toWriter(bytes []byte) (err error) { 89 e.count += len(bytes) 90 if traceEnabled { 91 zlog.Debug(" > encode: appending", zap.Stringer("hex", HexBytes(bytes)), zap.Int("pos", e.count)) 92 } 93 _, err = e.output.Write(bytes) 94 return 95 } 96 97 // Written returns the count of bytes written. 98 func (e *Encoder) Written() int { 99 return e.count 100 } 101 102 func (e *Encoder) WriteBytes(b []byte, writeLength bool) error { 103 if traceEnabled { 104 zlog.Debug("encode: write byte array", zap.Int("len", len(b))) 105 } 106 if writeLength { 107 if err := e.WriteLength(len(b)); err != nil { 108 return err 109 } 110 } 111 if len(b) == 0 { 112 return nil 113 } 114 return e.toWriter(b) 115 } 116 117 func (e *Encoder) Write(b []byte) (n int, err error) { 118 e.count += len(b) 119 if traceEnabled { 120 zlog.Debug(" > encode: appending", zap.Stringer("hex", HexBytes(b)), zap.Int("pos", e.count)) 121 } 122 return e.output.Write(b) 123 } 124 125 func (e *Encoder) WriteLength(length int) error { 126 if traceEnabled { 127 zlog.Debug("encode: write length", zap.Int("len", length)) 128 } 129 switch e.encoding { 130 case EncodingBin: 131 if err := e.WriteUVarInt(length); err != nil { 132 return err 133 } 134 case EncodingBorsh: 135 if err := e.WriteUint32(uint32(length), LE); err != nil { 136 return err 137 } 138 case EncodingCompactU16: 139 var buf []byte 140 EncodeCompactU16Length(&buf, length) 141 if err := e.WriteBytes(buf, false); err != nil { 142 return err 143 } 144 default: 145 panic(fmt.Errorf("encoding not implemented: %s", e.encoding)) 146 } 147 return nil 148 } 149 150 func (e *Encoder) WriteUVarInt(v int) (err error) { 151 if traceEnabled { 152 zlog.Debug("encode: write uvarint", zap.Int("val", v)) 153 } 154 155 buf := make([]byte, 8) 156 l := binary.PutUvarint(buf, uint64(v)) 157 return e.toWriter(buf[:l]) 158 } 159 160 func (e *Encoder) WriteVarInt(v int) (err error) { 161 if traceEnabled { 162 zlog.Debug("encode: write varint", zap.Int("val", v)) 163 } 164 165 buf := make([]byte, 8) 166 l := binary.PutVarint(buf, int64(v)) 167 return e.toWriter(buf[:l]) 168 } 169 170 func (e *Encoder) WriteByte(b byte) (err error) { 171 if traceEnabled { 172 zlog.Debug("encode: write byte", zap.Uint8("val", b)) 173 } 174 return e.toWriter([]byte{b}) 175 } 176 177 func (e *Encoder) WriteOption(b bool) (err error) { 178 if traceEnabled { 179 zlog.Debug("encode: write option", zap.Bool("val", b)) 180 } 181 return e.WriteBool(b) 182 } 183 184 func (e *Encoder) WriteCOption(b bool) (err error) { 185 if traceEnabled { 186 zlog.Debug("encode: write c-option", zap.Bool("val", b)) 187 } 188 var num uint32 189 if b { 190 num = 1 191 } 192 return e.WriteUint32(num, LE) 193 } 194 195 func (e *Encoder) WriteBool(b bool) (err error) { 196 if traceEnabled { 197 zlog.Debug("encode: write bool", zap.Bool("val", b)) 198 } 199 var out byte 200 if b { 201 out = 1 202 } 203 return e.WriteByte(out) 204 } 205 206 func (e *Encoder) WriteUint8(i uint8) (err error) { 207 return e.WriteByte(i) 208 } 209 210 func (e *Encoder) WriteInt8(i int8) (err error) { 211 return e.WriteByte(uint8(i)) 212 } 213 214 func (e *Encoder) WriteUint16(i uint16, order binary.ByteOrder) (err error) { 215 if traceEnabled { 216 zlog.Debug("encode: write uint16", zap.Uint16("val", i)) 217 } 218 buf := make([]byte, TypeSize.Uint16) 219 order.PutUint16(buf, i) 220 return e.toWriter(buf) 221 } 222 223 func (e *Encoder) WriteInt16(i int16, order binary.ByteOrder) (err error) { 224 if traceEnabled { 225 zlog.Debug("encode: write int16", zap.Int16("val", i)) 226 } 227 return e.WriteUint16(uint16(i), order) 228 } 229 230 func (e *Encoder) WriteUint32(i uint32, order binary.ByteOrder) (err error) { 231 if traceEnabled { 232 zlog.Debug("encode: write uint32", zap.Uint32("val", i)) 233 } 234 buf := make([]byte, TypeSize.Uint32) 235 order.PutUint32(buf, i) 236 return e.toWriter(buf) 237 } 238 239 func (e *Encoder) WriteInt32(i int32, order binary.ByteOrder) (err error) { 240 if traceEnabled { 241 zlog.Debug("encode: write int32", zap.Int32("val", i)) 242 } 243 return e.WriteUint32(uint32(i), order) 244 } 245 246 func (e *Encoder) WriteUint64(i uint64, order binary.ByteOrder) (err error) { 247 if traceEnabled { 248 zlog.Debug("encode: write uint64", zap.Uint64("val", i)) 249 } 250 buf := make([]byte, TypeSize.Uint64) 251 order.PutUint64(buf, i) 252 return e.toWriter(buf) 253 } 254 255 func (e *Encoder) WriteInt64(i int64, order binary.ByteOrder) (err error) { 256 if traceEnabled { 257 zlog.Debug("encode: write int64", zap.Int64("val", i)) 258 } 259 return e.WriteUint64(uint64(i), order) 260 } 261 262 func (e *Encoder) WriteUint128(i Uint128, order binary.ByteOrder) (err error) { 263 if traceEnabled { 264 zlog.Debug("encode: write uint128", zap.Stringer("hex", i), zap.Uint64("lo", i.Lo), zap.Uint64("hi", i.Hi)) 265 } 266 buf := make([]byte, TypeSize.Uint128) 267 switch order { 268 case binary.LittleEndian: 269 order.PutUint64(buf[:8], i.Lo) 270 order.PutUint64(buf[8:], i.Hi) 271 case binary.BigEndian: 272 order.PutUint64(buf[:8], i.Hi) 273 order.PutUint64(buf[8:], i.Lo) 274 default: 275 return fmt.Errorf("invalid byte order: %v", order) 276 } 277 return e.toWriter(buf) 278 } 279 280 func (e *Encoder) WriteInt128(i Int128, order binary.ByteOrder) (err error) { 281 if traceEnabled { 282 zlog.Debug("encode: write int128", zap.Stringer("hex", i), zap.Uint64("lo", i.Lo), zap.Uint64("hi", i.Hi)) 283 } 284 buf := make([]byte, TypeSize.Uint128) 285 switch order { 286 case binary.LittleEndian: 287 order.PutUint64(buf[:8], i.Lo) 288 order.PutUint64(buf[8:], i.Hi) 289 case binary.BigEndian: 290 order.PutUint64(buf[:8], i.Hi) 291 order.PutUint64(buf[8:], i.Lo) 292 default: 293 return fmt.Errorf("invalid byte order: %v", order) 294 } 295 return e.toWriter(buf) 296 } 297 298 func (e *Encoder) WriteFloat32(f float32, order binary.ByteOrder) (err error) { 299 if traceEnabled { 300 zlog.Debug("encode: write float32", zap.Float32("val", f)) 301 } 302 303 if e.IsBorsh() { 304 if math.IsNaN(float64(f)) { 305 return errors.New("NaN float value") 306 } 307 } 308 309 i := math.Float32bits(f) 310 buf := make([]byte, TypeSize.Uint32) 311 order.PutUint32(buf, i) 312 313 return e.toWriter(buf) 314 } 315 316 func (e *Encoder) WriteFloat64(f float64, order binary.ByteOrder) (err error) { 317 if traceEnabled { 318 zlog.Debug("encode: write float64", zap.Float64("val", f)) 319 } 320 321 if e.IsBorsh() { 322 if math.IsNaN(float64(f)) { 323 return errors.New("NaN float value") 324 } 325 } 326 i := math.Float64bits(f) 327 buf := make([]byte, TypeSize.Uint64) 328 order.PutUint64(buf, i) 329 330 return e.toWriter(buf) 331 } 332 333 func (e *Encoder) WriteString(s string) (err error) { 334 if traceEnabled { 335 zlog.Debug("encode: write string", zap.String("val", s)) 336 } 337 return e.WriteBytes([]byte(s), true) 338 } 339 340 func (e *Encoder) WriteRustString(s string) (err error) { 341 err = e.WriteUint64(uint64(len(s)), binary.LittleEndian) 342 if err != nil { 343 return err 344 } 345 if traceEnabled { 346 zlog.Debug("encode: write Rust string", zap.String("val", s)) 347 } 348 return e.WriteBytes([]byte(s), false) 349 } 350 351 func (e *Encoder) WriteCompactU16(ln int) (err error) { 352 if traceEnabled { 353 zlog.Debug("encode: write compact-u16", zap.Int("val", ln)) 354 } 355 buf := make([]byte, 0) 356 EncodeCompactU16Length(&buf, ln) 357 return e.toWriter(buf) 358 } 359 360 func (e *Encoder) WriteCompactU16Length(ln int) (err error) { 361 return e.WriteCompactU16(ln) 362 } 363 364 func reflect_writeArrayOfBytes(e *Encoder, l int, rv reflect.Value) error { 365 arr := make([]byte, l) 366 for i := 0; i < l; i++ { 367 arr[i] = byte(rv.Index(i).Uint()) 368 } 369 return e.WriteBytes(arr, false) 370 } 371 372 func reflect_writeArrayOfUint16(e *Encoder, l int, rv reflect.Value, order binary.ByteOrder) error { 373 arr := make([]byte, l*2) 374 for i := 0; i < l; i++ { 375 order.PutUint16(arr[i*2:], uint16(rv.Index(i).Uint())) 376 } 377 return e.WriteBytes(arr, false) 378 } 379 380 func reflect_writeArrayOfUint32(e *Encoder, l int, rv reflect.Value, order binary.ByteOrder) error { 381 arr := make([]byte, l*4) 382 for i := 0; i < l; i++ { 383 order.PutUint32(arr[i*4:], uint32(rv.Index(i).Uint())) 384 } 385 return e.WriteBytes(arr, false) 386 } 387 388 func reflect_writeArrayOfUint64(e *Encoder, l int, rv reflect.Value, order binary.ByteOrder) error { 389 arr := make([]byte, l*8) 390 for i := 0; i < l; i++ { 391 order.PutUint64(arr[i*8:], uint64(rv.Index(i).Uint())) 392 } 393 return e.WriteBytes(arr, false) 394 } 395 396 // reflect_writeArrayOfUint_ is used for writing arrays/slices of uints of any size. 397 func reflect_writeArrayOfUint_(e *Encoder, l int, k reflect.Kind, rv reflect.Value, order binary.ByteOrder) error { 398 switch k { 399 // case reflect.Uint: 400 // // switch on system architecture (32 or 64 bit) 401 // if unsafe.Sizeof(uintptr(0)) == 4 { 402 // return reflect_writeArrayOfUint32(e, l, rv, order) 403 // } 404 // return reflect_writeArrayOfUint64(e, l, rv, order) 405 case reflect.Uint8: 406 return reflect_writeArrayOfBytes(e, l, rv) 407 case reflect.Uint16: 408 return reflect_writeArrayOfUint16(e, l, rv, order) 409 case reflect.Uint32: 410 return reflect_writeArrayOfUint32(e, l, rv, order) 411 case reflect.Uint64: 412 return reflect_writeArrayOfUint64(e, l, rv, order) 413 default: 414 return fmt.Errorf("unsupported kind: %v", k) 415 } 416 }