diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
| commit | 20ef0d92694465ac86b550df139e8366a0a2b4fa (patch) | |
| tree | 3f14589e1ce6eb9306a3af31c3a1f9e1af5ed637 /vendor/github.com/hamba/avro/v2/codec_fixed.go | |
| parent | 44e0d272c040cdc53a98b9f1dc58ae7da67752e6 (diff) | |
feat: connect to spicedb
Diffstat (limited to 'vendor/github.com/hamba/avro/v2/codec_fixed.go')
| -rw-r--r-- | vendor/github.com/hamba/avro/v2/codec_fixed.go | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/vendor/github.com/hamba/avro/v2/codec_fixed.go b/vendor/github.com/hamba/avro/v2/codec_fixed.go new file mode 100644 index 0000000..d6a642b --- /dev/null +++ b/vendor/github.com/hamba/avro/v2/codec_fixed.go @@ -0,0 +1,192 @@ +package avro + +import ( + "encoding/binary" + "fmt" + "math/big" + "reflect" + "unsafe" + + "github.com/modern-go/reflect2" +) + +func createDecoderOfFixed(fixed *FixedSchema, typ reflect2.Type) ValDecoder { + switch typ.Kind() { + case reflect.Array: + arrayType := typ.(reflect2.ArrayType) + if arrayType.Elem().Kind() != reflect.Uint8 || arrayType.Len() != fixed.Size() { + break + } + return &fixedCodec{arrayType: typ.(*reflect2.UnsafeArrayType)} + case reflect.Uint64: + if fixed.Size() != 8 { + break + } + + return &fixedUint64Codec{} + case reflect.Ptr: + ptrType := typ.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + + ls := fixed.Logical() + tpy1 := elemType.Type1() + if elemType.Kind() != reflect.Struct || !tpy1.ConvertibleTo(ratType) || ls == nil || + ls.Type() != Decimal { + break + } + dec := ls.(*DecimalLogicalSchema) + return &fixedDecimalCodec{prec: dec.Precision(), scale: dec.Scale(), size: fixed.Size()} + case reflect.Struct: + ls := fixed.Logical() + if ls == nil { + break + } + typ1 := typ.Type1() + if !typ1.ConvertibleTo(durType) || ls.Type() != Duration { + break + } + return &fixedDurationCodec{} + } + + return &errorDecoder{ + err: fmt.Errorf("avro: %s is unsupported for Avro %s, size=%d", typ.String(), fixed.Type(), fixed.Size()), + } +} + +func createEncoderOfFixed(fixed *FixedSchema, typ reflect2.Type) ValEncoder { + switch typ.Kind() { + case reflect.Array: + arrayType := typ.(reflect2.ArrayType) + if arrayType.Elem().Kind() != reflect.Uint8 || arrayType.Len() != fixed.Size() { + break + } + return &fixedCodec{arrayType: typ.(*reflect2.UnsafeArrayType)} + case reflect.Uint64: + if fixed.Size() != 8 { + break + } + + return &fixedUint64Codec{} + case reflect.Ptr: + ptrType := typ.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + + ls := fixed.Logical() + tpy1 := elemType.Type1() + if elemType.Kind() != reflect.Struct || !tpy1.ConvertibleTo(ratType) || ls == nil || + ls.Type() != Decimal { + break + } + dec := ls.(*DecimalLogicalSchema) + return &fixedDecimalCodec{prec: dec.Precision(), scale: dec.Scale(), size: fixed.Size()} + + case reflect.Struct: + ls := fixed.Logical() + if ls == nil { + break + } + typ1 := typ.Type1() + if typ1.ConvertibleTo(durType) && ls.Type() == Duration { + return &fixedDurationCodec{} + } + } + + return &errorEncoder{ + err: fmt.Errorf("avro: %s is unsupported for Avro %s, size=%d", typ.String(), fixed.Type(), fixed.Size()), + } +} + +type fixedUint64Codec [8]byte + +func (c *fixedUint64Codec) Decode(ptr unsafe.Pointer, r *Reader) { + buffer := c[:] + r.Read(buffer) + *(*uint64)(ptr) = binary.BigEndian.Uint64(buffer) +} + +func (c *fixedUint64Codec) Encode(ptr unsafe.Pointer, w *Writer) { + buffer := c[:] + binary.BigEndian.PutUint64(buffer, *(*uint64)(ptr)) + _, _ = w.Write(buffer) +} + +type fixedCodec struct { + arrayType *reflect2.UnsafeArrayType +} + +func (c *fixedCodec) Decode(ptr unsafe.Pointer, r *Reader) { + for i := range c.arrayType.Len() { + c.arrayType.UnsafeSetIndex(ptr, i, reflect2.PtrOf(r.readByte())) + } +} + +func (c *fixedCodec) Encode(ptr unsafe.Pointer, w *Writer) { + for i := range c.arrayType.Len() { + bytePtr := c.arrayType.UnsafeGetIndex(ptr, i) + w.writeByte(*((*byte)(bytePtr))) + } +} + +type fixedDecimalCodec struct { + prec int + scale int + size int +} + +func (c *fixedDecimalCodec) Decode(ptr unsafe.Pointer, r *Reader) { + b := make([]byte, c.size) + r.Read(b) + *((**big.Rat)(ptr)) = ratFromBytes(b, c.scale) +} + +func (c *fixedDecimalCodec) Encode(ptr unsafe.Pointer, w *Writer) { + r := *((**big.Rat)(ptr)) + scale := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(c.scale)), nil) + i := (&big.Int{}).Mul(r.Num(), scale) + i = i.Div(i, r.Denom()) + + var b []byte + switch i.Sign() { + case 0: + b = make([]byte, c.size) + + case 1: + b = i.Bytes() + if b[0]&0x80 > 0 { + b = append([]byte{0}, b...) + } + if len(b) < c.size { + padded := make([]byte, c.size) + copy(padded[c.size-len(b):], b) + b = padded + } + + case -1: + b = i.Add(i, (&big.Int{}).Lsh(one, uint(c.size*8))).Bytes() + } + + _, _ = w.Write(b) +} + +type fixedDurationCodec struct{} + +func (*fixedDurationCodec) Decode(ptr unsafe.Pointer, r *Reader) { + b := make([]byte, 12) + r.Read(b) + var duration LogicalDuration + duration.Months = binary.LittleEndian.Uint32(b[0:4]) + duration.Days = binary.LittleEndian.Uint32(b[4:8]) + duration.Milliseconds = binary.LittleEndian.Uint32(b[8:12]) + *((*LogicalDuration)(ptr)) = duration +} + +func (*fixedDurationCodec) Encode(ptr unsafe.Pointer, w *Writer) { + duration := (*LogicalDuration)(ptr) + b := make([]byte, 4) + binary.LittleEndian.PutUint32(b, duration.Months) + _, _ = w.Write(b) + binary.LittleEndian.PutUint32(b, duration.Days) + _, _ = w.Write(b) + binary.LittleEndian.PutUint32(b, duration.Milliseconds) + _, _ = w.Write(b) +} |
