Skip to content

Commit

Permalink
Improve panic handling and add a test for lenient decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
ilija42 committed Dec 24, 2024
1 parent 7bcaf47 commit 2a74587
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 15 deletions.
18 changes: 12 additions & 6 deletions pkg/solana/codec/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@ import (
)

type Decoder struct {
definitions map[string]Entry
codecFromTypeCodec encodings.LenientCodecFromTypeCodec
definitions map[string]Entry
lenientFromTypeCodec encodings.LenientCodecFromTypeCodec
}

var _ commontypes.Decoder = &Decoder{}

func (d *Decoder) Decode(ctx context.Context, raw []byte, into any, itemType string) (err error) {
if d.codecFromTypeCodec == nil {
d.codecFromTypeCodec = make(encodings.LenientCodecFromTypeCodec)
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from: %v, while decoding %q", r, itemType)
}
}()

if d.lenientFromTypeCodec == nil {
d.lenientFromTypeCodec = make(encodings.LenientCodecFromTypeCodec)
for k, v := range d.definitions {
d.codecFromTypeCodec[k] = v
d.lenientFromTypeCodec[k] = v
}
}

return d.codecFromTypeCodec.Decode(ctx, raw, into, itemType)
return d.lenientFromTypeCodec.Decode(ctx, raw, into, itemType)
}

func (d *Decoder) GetMaxDecodingSize(_ context.Context, n int, itemType string) (int, error) {
Expand Down
6 changes: 3 additions & 3 deletions pkg/solana/codec/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type testErrDecodeRemainingBytes struct {
}

func (t *testErrDecodeRemainingBytes) Decode(_ []byte) (interface{}, []byte, error) {
return nil, []byte{1}, nil
return struct{}{}, []byte{1}, nil
}

func TestDecoder_Decode_Errors(t *testing.T) {
Expand All @@ -45,10 +45,10 @@ func TestDecoder_Decode_Errors(t *testing.T) {
require.Error(t, d.Decode(tests.Context(t), []byte{}, &into, someType))
})

t.Run("error when remaining bytes exist after decode", func(t *testing.T) {
t.Run("remaining bytes exist after decode is ok", func(t *testing.T) {
d := &Decoder{definitions: map[string]Entry{}}
d.definitions[someType] = &testErrDecodeRemainingBytes{}
require.Error(t, d.Decode(tests.Context(t), []byte{}, &into, someType))
require.NoError(t, d.Decode(tests.Context(t), []byte{}, &into, someType))
})
}

Expand Down
18 changes: 12 additions & 6 deletions pkg/solana/codec/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@ import (
)

type Encoder struct {
definitions map[string]Entry
codecFromTypeCodec encodings.CodecFromTypeCodec
definitions map[string]Entry
lenientCodecFromTypeCodec encodings.LenientCodecFromTypeCodec
}

var _ commontypes.Encoder = &Encoder{}

func (e *Encoder) Encode(ctx context.Context, item any, itemType string) (res []byte, err error) {
if e.codecFromTypeCodec == nil {
e.codecFromTypeCodec = make(encodings.CodecFromTypeCodec)
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from: %v, while encoding %q", r, itemType)
}
}()

if e.lenientCodecFromTypeCodec == nil {
e.lenientCodecFromTypeCodec = make(encodings.LenientCodecFromTypeCodec)
for k, v := range e.definitions {
e.codecFromTypeCodec[k] = v
e.lenientCodecFromTypeCodec[k] = v
}
}

return e.codecFromTypeCodec.Encode(ctx, item, itemType)
return e.lenientCodecFromTypeCodec.Encode(ctx, item, itemType)
}

func (e *Encoder) GetMaxEncodingSize(_ context.Context, n int, itemType string) (int, error) {
Expand Down

0 comments on commit 2a74587

Please sign in to comment.