From d36d97d7c9f7a76b2b666db39bcae08c65ce3583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Sat, 30 Mar 2024 10:54:06 +0100 Subject: [PATCH 1/4] Support for encoding *uint8, *uint16, *uint32, and *uint64 --- decoder.go | 52 ++++++++++++++++++ decoder_test.go | 48 +++++++++++++++++ encoder.go | 60 +++++++++++++++++++++ encoder_test.go | 87 +++++++++++++++++++++++++++++++ generate.go | 12 +++++ generate_test.go | 133 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 392 insertions(+) diff --git a/decoder.go b/decoder.go index ecacdc2..7a28496 100644 --- a/decoder.go +++ b/decoder.go @@ -523,3 +523,55 @@ func DecodeOption[V any, H DecodablePtr[V]](d *Decoder) (*V, int, error) { } return &empty, total + n, nil } + +func DecodeBytePtr(d *Decoder) (*byte, int, error) { + exists, total, err := DecodeBool(d) + if !exists || err != nil { + return nil, total, err + } + + v, n, err := DecodeByte(d) + if err != nil { + return nil, 0, err + } + return &v, total + n, nil +} + +func DecodeCompact16Ptr(d *Decoder) (*uint16, int, error) { + exists, total, err := DecodeBool(d) + if !exists || err != nil { + return nil, total, err + } + + v, n, err := DecodeCompact16(d) + if err != nil { + return nil, 0, err + } + return &v, total + n, nil +} + +func DecodeCompact32Ptr(d *Decoder) (*uint32, int, error) { + exists, total, err := DecodeBool(d) + if !exists || err != nil { + return nil, total, err + } + + v, n, err := DecodeCompact32(d) + if err != nil { + return nil, 0, err + } + return &v, total + n, nil +} + +func DecodeCompact64Ptr(d *Decoder) (*uint64, int, error) { + exists, total, err := DecodeBool(d) + if !exists || err != nil { + return nil, total, err + } + + v, n, err := DecodeCompact64(d) + if err != nil { + return nil, 0, err + } + return &v, total + n, nil +} diff --git a/decoder_test.go b/decoder_test.go index 4f61711..38ed7d5 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -37,6 +37,14 @@ func testEncode(tb testing.TB, value any) []byte { _, err = EncodeCompact32(enc, val) case uint64: _, err = EncodeCompact64(enc, val) + case *uint8: + _, err = EncodeBytePtr(enc, val) + case *uint16: + _, err = EncodeCompact16Ptr(enc, val) + case *uint32: + _, err = EncodeCompact32Ptr(enc, val) + case *uint64: + _, err = EncodeCompact64Ptr(enc, val) case []byte: _, err = EncodeByteSlice(enc, val) case []uint16: @@ -69,6 +77,14 @@ func expectEqual(tb testing.TB, value any, r io.Reader) { rst, _, err = DecodeCompact32(dec) case uint64: rst, _, err = DecodeCompact64(dec) + case *uint8: + rst, _, err = DecodeBytePtr(dec) + case *uint16: + rst, _, err = DecodeCompact16Ptr(dec) + case *uint32: + rst, _, err = DecodeCompact32Ptr(dec) + case *uint64: + rst, _, err = DecodeCompact64Ptr(dec) case []byte: rst, _, err = DecodeByteSlice(dec) case []uint16: @@ -107,6 +123,38 @@ func TestReadFull(t *testing.T) { desc: "uint64", expect: uint64(math.MaxUint64), }, + { + desc: "*uint8", + expect: newInteger[uint8](math.MaxUint8), + }, + { + desc: "nil *uint8", + expect: (*uint8)(nil), + }, + { + desc: "*uint16", + expect: newInteger[uint16](math.MaxUint8), + }, + { + desc: "nil *uint16", + expect: (*uint16)(nil), + }, + { + desc: "*uint32", + expect: newInteger[uint32](math.MaxUint8), + }, + { + desc: "nil *uint32", + expect: (*uint32)(nil), + }, + { + desc: "*uint64", + expect: newInteger[uint64](math.MaxUint8), + }, + { + desc: "nil *uint64", + expect: (*uint64)(nil), + }, { desc: "byte slice", expect: []byte("dsa1232131312dsada123312"), diff --git a/encoder.go b/encoder.go index f2cbcf6..4b2b09c 100644 --- a/encoder.go +++ b/encoder.go @@ -365,6 +365,66 @@ func EncodeOption[V any, H EncodablePtr[V]](e *Encoder, value *V) (int, error) { return total + n, nil } +func EncodeBytePtr(e *Encoder, value *byte) (int, error) { + if value == nil { + return EncodeBool(e, false) + } + total, err := EncodeBool(e, true) + if err != nil { + return 0, err + } + n, err := EncodeByte(e, *value) + if err != nil { + return 0, err + } + return total + n, err +} + +func EncodeCompact16Ptr(e *Encoder, value *uint16) (int, error) { + if value == nil { + return EncodeBool(e, false) + } + total, err := EncodeBool(e, true) + if err != nil { + return 0, err + } + n, err := EncodeCompact16(e, *value) + if err != nil { + return 0, err + } + return total + n, err +} + +func EncodeCompact32Ptr(e *Encoder, value *uint32) (int, error) { + if value == nil { + return EncodeBool(e, false) + } + total, err := EncodeBool(e, true) + if err != nil { + return 0, err + } + n, err := EncodeCompact32(e, *value) + if err != nil { + return 0, err + } + return total + n, err +} + +func EncodeCompact64Ptr(e *Encoder, value *uint64) (int, error) { + if value == nil { + return EncodeBool(e, false) + } + total, err := EncodeBool(e, true) + if err != nil { + return 0, err + } + n, err := EncodeCompact64(e, *value) + if err != nil { + return 0, err + } + return total + n, err +} + func EncodeStruct[V any, H EncodablePtr[V]](e *Encoder, value V) (int, error) { n, err := H(&value).EncodeScale(e) if err != nil { diff --git a/encoder_test.go b/encoder_test.go index 3e5a6cd..5e8e895 100644 --- a/encoder_test.go +++ b/encoder_test.go @@ -129,6 +129,57 @@ func uint64TestCases() []compactTestCase[uint64] { } } +func newInteger[T ~uint8 | ~uint16 | ~uint32 | ~uint64](v T) *T { + return &v +} + +func uint8PtrTestCases() []compactTestCase[*uint8] { + return []compactTestCase[*uint8]{ + {nil, []byte{0}}, + {newInteger[uint8](1), []byte{1, 1}}, + {newInteger[uint8](math.MaxUint8), []byte{1, math.MaxUint8}}, + } +} + +func uint16PtrTestCases() []compactTestCase[*uint16] { + return []compactTestCase[*uint16]{ + {nil, []byte{0}}, + {newInteger[uint16](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, + {newInteger[uint16](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, + } +} + +func uint32PtrTestCases() []compactTestCase[*uint32] { + return []compactTestCase[*uint32]{ + {nil, []byte{0}}, + {newInteger[uint32](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, + {newInteger[uint32](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, + {newInteger[uint32](maxUint30), []byte{1, 0b1111_1110, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, + {newInteger[uint32](math.MaxUint32), []byte{1, 0b0000_0011, 0b1111_1111, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, + } +} + +func uint64PtrTestCases() []compactTestCase[*uint64] { + return []compactTestCase[*uint64]{ + {nil, []byte{0}}, + {newInteger[uint64](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, + {newInteger[uint64](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, + {newInteger[uint64](math.MaxUint32), []byte{1, 0b0000_0011, 0b1111_1111, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, + {newInteger[uint64](math.MaxUint64), []byte{ + 1, + 0b0001_0011, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + }, + }, + } +} func mustDecodeHex(hexStr string) []byte { b, err := hex.DecodeString(hexStr) if err != nil { @@ -168,6 +219,14 @@ func encodeTest[T any](t *testing.T, value T, expect []byte) { _, err = EncodeCompact32(enc, typed) case uint64: _, err = EncodeCompact64(enc, typed) + case *uint8: + _, err = EncodeBytePtr(enc, typed) + case *uint16: + _, err = EncodeCompact16Ptr(enc, typed) + case *uint32: + _, err = EncodeCompact32Ptr(enc, typed) + case *uint64: + _, err = EncodeCompact64Ptr(enc, typed) case []uint16: _, err = EncodeUint16Slice(enc, typed) case []uint32: @@ -210,6 +269,34 @@ func TestEncodeCompactIntegers(t *testing.T) { }) } }) + t.Run("*uint8", func(t *testing.T) { + for _, tc := range uint8PtrTestCases() { + t.Run("", func(t *testing.T) { + encodeTest(t, tc.value, tc.expect) + }) + } + }) + t.Run("*uint16", func(t *testing.T) { + for _, tc := range uint16PtrTestCases() { + t.Run("", func(t *testing.T) { + encodeTest(t, tc.value, tc.expect) + }) + } + }) + t.Run("*uint32", func(t *testing.T) { + for _, tc := range uint32PtrTestCases() { + t.Run("", func(t *testing.T) { + encodeTest(t, tc.value, tc.expect) + }) + } + }) + t.Run("*uint64", func(t *testing.T) { + for _, tc := range uint64PtrTestCases() { + t.Run("", func(t *testing.T) { + encodeTest(t, tc.value, tc.expect) + }) + } + }) t.Run("[]uint16", func(t *testing.T) { for _, tc := range uint16SliceTestCases() { t.Run("", func(t *testing.T) { diff --git a/generate.go b/generate.go index 2b6c091..b42688f 100644 --- a/generate.go +++ b/generate.go @@ -308,6 +308,18 @@ func getScaleType(parentType reflect.Type, field reflect.StructField) (scaleType case reflect.Struct: return scaleType{Name: "Object"}, nil case reflect.Ptr: + if field.Type.Elem().Kind() == reflect.Uint8 && !field.Type.Elem().Implements(encodableType) { + return scaleType{Name: "BytePtr"}, nil + } + if field.Type.Elem().Kind() == reflect.Uint16 && !field.Type.Elem().Implements(encodableType) { + return scaleType{Name: "Compact16Ptr"}, nil + } + if field.Type.Elem().Kind() == reflect.Uint32 && !field.Type.Elem().Implements(encodableType) { + return scaleType{Name: "Compact32Ptr"}, nil + } + if field.Type.Elem().Kind() == reflect.Uint64 && !field.Type.Elem().Implements(encodableType) { + return scaleType{Name: "Compact64Ptr"}, nil + } return scaleType{Name: "Option"}, nil case reflect.Slice: if field.Type.Elem().Kind() == reflect.Slice && field.Type.Elem().Elem().Kind() == reflect.Uint8 { diff --git a/generate_test.go b/generate_test.go index 2d73930..31d8714 100644 --- a/generate_test.go +++ b/generate_test.go @@ -7,6 +7,12 @@ import ( "github.com/stretchr/testify/require" ) +type newU8 uint8 + +func (newU8) EncodeScale(enc *Encoder) (int, error) { + panic("uninmplemented") +} + type newU16 uint16 func (newU16) EncodeScale(enc *Encoder) (int, error) { @@ -120,3 +126,130 @@ func Test_getScaleType_Slices(t *testing.T) { require.Equal(t, "Uint64SliceWithLimit", scaleT.Name) }) } + +func Test_getScaleTypePtrs(t *testing.T) { + t.Run("*uint8", func(t *testing.T) { + type Foo struct { + Ptr *uint8 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "BytePtr", scaleT.Name) + }) + t.Run("*newU8 (implements Encodable)", func(t *testing.T) { + type Foo struct { + Ptr *newU8 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Option", scaleT.Name) + }) + t.Run("*newU8 (doesn't implement Encodable)", func(t *testing.T) { + type newT uint8 + type Foo struct { + Ptr *newT + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "BytePtr", scaleT.Name) + }) + t.Run("*uint16", func(t *testing.T) { + type Foo struct { + Ptr *uint16 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Compact16Ptr", scaleT.Name) + }) + t.Run("*newU16 (implements Encodable)", func(t *testing.T) { + type Foo struct { + Ptr *newU16 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Option", scaleT.Name) + }) + t.Run("*newU16 (doesn't implement Encodable)", func(t *testing.T) { + type newT uint16 + type Foo struct { + Ptr *newT + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Compact16Ptr", scaleT.Name) + }) + t.Run("*uint32", func(t *testing.T) { + type Foo struct { + Ptr *uint32 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Compact32Ptr", scaleT.Name) + }) + t.Run("*newU32 (implements Encodable)", func(t *testing.T) { + type Foo struct { + Ptr *newU32 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Option", scaleT.Name) + }) + t.Run("*newU32 (doesn't implement Encodable)", func(t *testing.T) { + type newT uint32 + type Foo struct { + Ptr *newT + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Compact32Ptr", scaleT.Name) + }) + t.Run("*uint64", func(t *testing.T) { + type Foo struct { + Ptr *uint64 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Compact64Ptr", scaleT.Name) + }) + t.Run("*newU64 (implements Encodable)", func(t *testing.T) { + type Foo struct { + Ptr *newU64 + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Option", scaleT.Name) + }) + t.Run("*newU64 (doesn't implement Encodable)", func(t *testing.T) { + type newT uint64 + type Foo struct { + Ptr *newT + } + + rtype := reflect.TypeOf(Foo{}) + scaleT, err := getScaleType(rtype, rtype.Field(0)) + require.NoError(t, err) + require.Equal(t, "Compact64Ptr", scaleT.Name) + }) +} From bf193157568522249fe8da9405059865a2794c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Sat, 30 Mar 2024 11:05:21 +0100 Subject: [PATCH 2/4] Update readme --- README.md | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 7eee456..1116b09 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,27 @@ ## Types -golang | notes -------------|------------------------------------------------------------------- -[]byte | length prefixed byte array with length as u32 compact integer -string | same as []byte -[...]byte | appended to the result -bool | 1 byte, 0 for false, 1 for true -Object{} | concatenation of fields -*Object{} | Option. 0 for nil, 1 for Object{}. if 1 - decode Object{} -uint8 | compact u8 [TODO no need for compact u8] -uint16 | compact u16 -uint32 | compact u32 -uint34 | compact u64 -[]uint16 | length prefixed (compact u32) followed by compact u16s -[]uint32 | length prefixed (compact u32) followed by compact u32s -[]uint64 | length prefixed (compact u32) followed by compact u64s -[...]Object | array with objects. encoded by consecutively encoding every object -[]Object | slice with objects. prefixed with compact u32 +| golang | notes | example | +| ----------- | ------------------------------------------------------------------ | ----------------------------------------------------- | +| []byte | length prefixed byte array with length as u32 compact integer | +| string | same as []byte | +| [...]byte | appended to the result | +| bool | 1 byte, 0 for false, 1 for true | +| Object{} | concatenation of fields | +| *Object{} | Option. 0 for nil, 1 for Object{}. if 1 - decode Object{} | +| uint8 | compact u8 [TODO no need for compact u8] | +| uint16 | compact u16 | +| uint32 | compact u32 | +| uint34 | compact u64 | +| *uint8 | Option (0 for nil, 1 otherwise), followed by fixed-width u8 | `&255 -> 01FF` | +| *uint16 | Option (0 for nil, 1 otherwise), followed by compact u16 | `&255 -> 01FD03` | +| *uint32 | Option (0 for nil, 1 otherwise), followed by compact u32 | `&255 -> 01FD03` | +| *uint34 | Option (0 for nil, 1 otherwise), followed by compact u64 | `&255 -> 01FD03` | +| []uint16 | length prefixed (compact u32) followed by compact u16s | `[4, 15, 23, u16::MAX] -> 10103C5CFEFF0300` | +| []uint32 | length prefixed (compact u32) followed by compact u32s | `[4, 15, 23, u32::MAX] -> 10103C5C03FFFFFFFF` | +| []uint64 | length prefixed (compact u32) followed by compact u64s | `[4, 15, 23, u64::MAX] -> 10103C5C13FFFFFFFFFFFFFFFF` | +| [...]Object | array with objects. encoded by consecutively encoding every object | +| []Object | slice with objects. prefixed with compact u32 | Not implemented: From f6a808ee4d7022f07391b79d9404170355852c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Sat, 30 Mar 2024 11:12:39 +0100 Subject: [PATCH 3/4] Satisfy linter --- encoder_test.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/encoder_test.go b/encoder_test.go index 5e8e895..5ed5451 100644 --- a/encoder_test.go +++ b/encoder_test.go @@ -155,7 +155,14 @@ func uint32PtrTestCases() []compactTestCase[*uint32] { {newInteger[uint32](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, {newInteger[uint32](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, {newInteger[uint32](maxUint30), []byte{1, 0b1111_1110, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, - {newInteger[uint32](math.MaxUint32), []byte{1, 0b0000_0011, 0b1111_1111, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, + {newInteger[uint32](math.MaxUint32), []byte{ + 1, + 0b0000_0011, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + }}, } } @@ -164,7 +171,14 @@ func uint64PtrTestCases() []compactTestCase[*uint64] { {nil, []byte{0}}, {newInteger[uint64](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, {newInteger[uint64](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, - {newInteger[uint64](math.MaxUint32), []byte{1, 0b0000_0011, 0b1111_1111, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, + {newInteger[uint64](math.MaxUint32), []byte{ + 1, + 0b0000_0011, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + 0b1111_1111, + }}, {newInteger[uint64](math.MaxUint64), []byte{ 1, 0b0001_0011, @@ -176,10 +190,10 @@ func uint64PtrTestCases() []compactTestCase[*uint64] { 0b1111_1111, 0b1111_1111, 0b1111_1111, - }, - }, + }}, } } + func mustDecodeHex(hexStr string) []byte { b, err := hex.DecodeString(hexStr) if err != nil { From 7274b9989f5aa5412833360a4d9e6ec02d649b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 4 Apr 2024 12:08:19 +0200 Subject: [PATCH 4/4] Review feedback. Encode *uint8 as compact --- README.md | 4 ++-- decoder.go | 4 ++-- decoder_test.go | 12 ++++++------ encoder.go | 4 ++-- encoder_test.go | 29 +++++++++++++++-------------- generate.go | 2 +- generate_test.go | 4 ++-- 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 1116b09..943a84f 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ | uint16 | compact u16 | | uint32 | compact u32 | | uint34 | compact u64 | -| *uint8 | Option (0 for nil, 1 otherwise), followed by fixed-width u8 | `&255 -> 01FF` | +| *uint8 | Option (0 for nil, 1 otherwise), followed by compact u8 | `&64 -> 01FC`; `&255 -> 01FD03` | | *uint16 | Option (0 for nil, 1 otherwise), followed by compact u16 | `&255 -> 01FD03` | | *uint32 | Option (0 for nil, 1 otherwise), followed by compact u32 | `&255 -> 01FD03` | -| *uint34 | Option (0 for nil, 1 otherwise), followed by compact u64 | `&255 -> 01FD03` | +| *uint64 | Option (0 for nil, 1 otherwise), followed by compact u64 | `&255 -> 01FD03` | | []uint16 | length prefixed (compact u32) followed by compact u16s | `[4, 15, 23, u16::MAX] -> 10103C5CFEFF0300` | | []uint32 | length prefixed (compact u32) followed by compact u32s | `[4, 15, 23, u32::MAX] -> 10103C5C03FFFFFFFF` | | []uint64 | length prefixed (compact u32) followed by compact u64s | `[4, 15, 23, u64::MAX] -> 10103C5C13FFFFFFFFFFFFFFFF` | diff --git a/decoder.go b/decoder.go index 7a28496..03c2af3 100644 --- a/decoder.go +++ b/decoder.go @@ -524,13 +524,13 @@ func DecodeOption[V any, H DecodablePtr[V]](d *Decoder) (*V, int, error) { return &empty, total + n, nil } -func DecodeBytePtr(d *Decoder) (*byte, int, error) { +func DecodeCompact8Ptr(d *Decoder) (*uint8, int, error) { exists, total, err := DecodeBool(d) if !exists || err != nil { return nil, total, err } - v, n, err := DecodeByte(d) + v, n, err := DecodeCompact8(d) if err != nil { return nil, 0, err } diff --git a/decoder_test.go b/decoder_test.go index 38ed7d5..3c7dd22 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -38,7 +38,7 @@ func testEncode(tb testing.TB, value any) []byte { case uint64: _, err = EncodeCompact64(enc, val) case *uint8: - _, err = EncodeBytePtr(enc, val) + _, err = EncodeCompact8Ptr(enc, val) case *uint16: _, err = EncodeCompact16Ptr(enc, val) case *uint32: @@ -78,7 +78,7 @@ func expectEqual(tb testing.TB, value any, r io.Reader) { case uint64: rst, _, err = DecodeCompact64(dec) case *uint8: - rst, _, err = DecodeBytePtr(dec) + rst, _, err = DecodeCompact8Ptr(dec) case *uint16: rst, _, err = DecodeCompact16Ptr(dec) case *uint32: @@ -125,7 +125,7 @@ func TestReadFull(t *testing.T) { }, { desc: "*uint8", - expect: newInteger[uint8](math.MaxUint8), + expect: intPtr[uint8](math.MaxUint8), }, { desc: "nil *uint8", @@ -133,7 +133,7 @@ func TestReadFull(t *testing.T) { }, { desc: "*uint16", - expect: newInteger[uint16](math.MaxUint8), + expect: intPtr[uint16](math.MaxUint8), }, { desc: "nil *uint16", @@ -141,7 +141,7 @@ func TestReadFull(t *testing.T) { }, { desc: "*uint32", - expect: newInteger[uint32](math.MaxUint8), + expect: intPtr[uint32](math.MaxUint8), }, { desc: "nil *uint32", @@ -149,7 +149,7 @@ func TestReadFull(t *testing.T) { }, { desc: "*uint64", - expect: newInteger[uint64](math.MaxUint8), + expect: intPtr[uint64](math.MaxUint8), }, { desc: "nil *uint64", diff --git a/encoder.go b/encoder.go index 4b2b09c..85b278f 100644 --- a/encoder.go +++ b/encoder.go @@ -365,7 +365,7 @@ func EncodeOption[V any, H EncodablePtr[V]](e *Encoder, value *V) (int, error) { return total + n, nil } -func EncodeBytePtr(e *Encoder, value *byte) (int, error) { +func EncodeCompact8Ptr(e *Encoder, value *uint8) (int, error) { if value == nil { return EncodeBool(e, false) } @@ -373,7 +373,7 @@ func EncodeBytePtr(e *Encoder, value *byte) (int, error) { if err != nil { return 0, err } - n, err := EncodeByte(e, *value) + n, err := EncodeCompact8(e, *value) if err != nil { return 0, err } diff --git a/encoder_test.go b/encoder_test.go index 5ed5451..296a2ce 100644 --- a/encoder_test.go +++ b/encoder_test.go @@ -129,33 +129,34 @@ func uint64TestCases() []compactTestCase[uint64] { } } -func newInteger[T ~uint8 | ~uint16 | ~uint32 | ~uint64](v T) *T { +func intPtr[T ~uint8 | ~uint16 | ~uint32 | ~uint64](v T) *T { return &v } func uint8PtrTestCases() []compactTestCase[*uint8] { return []compactTestCase[*uint8]{ {nil, []byte{0}}, - {newInteger[uint8](1), []byte{1, 1}}, - {newInteger[uint8](math.MaxUint8), []byte{1, math.MaxUint8}}, + {intPtr[uint8](1), []byte{1, 0b0000_0100}}, + {intPtr[uint8](maxUint6), []byte{1, 0b1111_1100}}, + {intPtr[uint8](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, } } func uint16PtrTestCases() []compactTestCase[*uint16] { return []compactTestCase[*uint16]{ {nil, []byte{0}}, - {newInteger[uint16](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, - {newInteger[uint16](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, + {intPtr[uint16](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, + {intPtr[uint16](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, } } func uint32PtrTestCases() []compactTestCase[*uint32] { return []compactTestCase[*uint32]{ {nil, []byte{0}}, - {newInteger[uint32](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, - {newInteger[uint32](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, - {newInteger[uint32](maxUint30), []byte{1, 0b1111_1110, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, - {newInteger[uint32](math.MaxUint32), []byte{ + {intPtr[uint32](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, + {intPtr[uint32](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, + {intPtr[uint32](maxUint30), []byte{1, 0b1111_1110, 0b1111_1111, 0b1111_1111, 0b1111_1111}}, + {intPtr[uint32](math.MaxUint32), []byte{ 1, 0b0000_0011, 0b1111_1111, @@ -169,9 +170,9 @@ func uint32PtrTestCases() []compactTestCase[*uint32] { func uint64PtrTestCases() []compactTestCase[*uint64] { return []compactTestCase[*uint64]{ {nil, []byte{0}}, - {newInteger[uint64](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, - {newInteger[uint64](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, - {newInteger[uint64](math.MaxUint32), []byte{ + {intPtr[uint64](maxUint8), []byte{1, 0b1111_1101, 0b0000_0011}}, + {intPtr[uint64](maxUint16), []byte{1, 0b1111_1110, 0b1111_1111, 0b0000_0011, 0b0000_0000}}, + {intPtr[uint64](math.MaxUint32), []byte{ 1, 0b0000_0011, 0b1111_1111, @@ -179,7 +180,7 @@ func uint64PtrTestCases() []compactTestCase[*uint64] { 0b1111_1111, 0b1111_1111, }}, - {newInteger[uint64](math.MaxUint64), []byte{ + {intPtr[uint64](math.MaxUint64), []byte{ 1, 0b0001_0011, 0b1111_1111, @@ -234,7 +235,7 @@ func encodeTest[T any](t *testing.T, value T, expect []byte) { case uint64: _, err = EncodeCompact64(enc, typed) case *uint8: - _, err = EncodeBytePtr(enc, typed) + _, err = EncodeCompact8Ptr(enc, typed) case *uint16: _, err = EncodeCompact16Ptr(enc, typed) case *uint32: diff --git a/generate.go b/generate.go index b42688f..cc1748d 100644 --- a/generate.go +++ b/generate.go @@ -309,7 +309,7 @@ func getScaleType(parentType reflect.Type, field reflect.StructField) (scaleType return scaleType{Name: "Object"}, nil case reflect.Ptr: if field.Type.Elem().Kind() == reflect.Uint8 && !field.Type.Elem().Implements(encodableType) { - return scaleType{Name: "BytePtr"}, nil + return scaleType{Name: "Compact8Ptr"}, nil } if field.Type.Elem().Kind() == reflect.Uint16 && !field.Type.Elem().Implements(encodableType) { return scaleType{Name: "Compact16Ptr"}, nil diff --git a/generate_test.go b/generate_test.go index 31d8714..c11b24e 100644 --- a/generate_test.go +++ b/generate_test.go @@ -136,7 +136,7 @@ func Test_getScaleTypePtrs(t *testing.T) { rtype := reflect.TypeOf(Foo{}) scaleT, err := getScaleType(rtype, rtype.Field(0)) require.NoError(t, err) - require.Equal(t, "BytePtr", scaleT.Name) + require.Equal(t, "Compact8Ptr", scaleT.Name) }) t.Run("*newU8 (implements Encodable)", func(t *testing.T) { type Foo struct { @@ -157,7 +157,7 @@ func Test_getScaleTypePtrs(t *testing.T) { rtype := reflect.TypeOf(Foo{}) scaleT, err := getScaleType(rtype, rtype.Field(0)) require.NoError(t, err) - require.Equal(t, "BytePtr", scaleT.Name) + require.Equal(t, "Compact8Ptr", scaleT.Name) }) t.Run("*uint16", func(t *testing.T) { type Foo struct {