Skip to content

Commit

Permalink
[FEATURE] We now have a special error case CustomDeserializerError
Browse files Browse the repository at this point in the history
  • Loading branch information
Yoric committed Dec 26, 2023
1 parent 1c0460f commit 15f5b2f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 7 deletions.
67 changes: 60 additions & 7 deletions deserialize/deserialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,30 @@ func MakeKVListDeserializer[T any](options Options) (KVListDeserializer[T], erro
}, nil
}

// An error that arises because of a bug in a custom deserializer.
type CustomDeserializerError struct {
// The operation that failed, e.g. "initialize", "orMethod".
Operation string

// The kind of value we were applying it to, e.g. "outer", "struct", "map", "ptr", "field".
Structure string

// The underlying error.
Wrapped error
}

// Return the user-facing message.
func (e CustomDeserializerError) Error() string {
return e.Wrapped.Error()
}

// Unwrap the error.
func (e CustomDeserializerError) Unwrap() error {
return e.Wrapped
}

var _ error = CustomDeserializerError{} //nolint:exhaustruct

// ----------------- Private

// Options used while setting up a deserializer.
Expand Down Expand Up @@ -395,7 +419,11 @@ func makeOuterStructDeserializer[T any](path string, options staticOptions) (*ma
if err != nil {
err = fmt.Errorf("at %s, encountered an error while initializing optional fields:\n\t * %w", path, err)
slog.Error("internal error during deserialization", "error", err)
return nil, err
return nil, CustomDeserializerError{
Wrapped: err,
Operation: "initializer",
Structure: "outer",
}

}
}
Expand Down Expand Up @@ -522,7 +550,11 @@ func makeStructDeserializerFromReflect(path string, typ reflect.Type, options st
if err != nil {
err = fmt.Errorf("at %s, encountered an error while initializing optional fields:\n\t * %w", path, err)
slog.Error("Internal error during deserialization", "error", err)
return err
return CustomDeserializerError{
Wrapped: err,
Operation: "initializer",
Structure: "struct",
}
}
}

Expand Down Expand Up @@ -552,7 +584,11 @@ func makeStructDeserializerFromReflect(path string, typ reflect.Type, options st
if err != nil {
err = fmt.Errorf("error in optional value at %s\n\t * %w", path, err)
slog.Error("Internal error during deserialization", "error", err)
return err
return CustomDeserializerError{
Wrapped: err,
Operation: "orMethod",
Structure: "struct",
}
}
reflected := reflect.ValueOf(constructed)
outPtr.Set(reflected)
Expand Down Expand Up @@ -654,7 +690,11 @@ func makeMapDeserializerFromReflect(path string, typ reflect.Type, options stati
if err != nil {
err = fmt.Errorf("at %s, encountered an error while initializing optional object:\n\t * %w", path, err)
slog.Error("Internal error during deserialization", "error", err)
return err
return CustomDeserializerError{
Wrapped: err,
Operation: "initialize",
Structure: "map",
}
}
}

Expand Down Expand Up @@ -685,7 +725,11 @@ func makeMapDeserializerFromReflect(path string, typ reflect.Type, options stati
if err != nil {
err = fmt.Errorf("error in optional object at %s\n\t * %w", path, err)
slog.Error("Internal error during deserialization", "error", err)
return err
return CustomDeserializerError{
Wrapped: err,
Operation: "orMethod",
Structure: "map",
}
}
reflected := reflect.ValueOf(constructed)
outPtr.Set(reflected)
Expand Down Expand Up @@ -724,6 +768,7 @@ func makeMapDeserializerFromReflect(path string, typ reflect.Type, options stati
subInValue, ok := inMap.Lookup(k)
if !ok {
slog.Error("Internal error while ranging over map: missing value", "path", path, "key", k)
// Hobble on.
continue
}

Expand Down Expand Up @@ -891,7 +936,11 @@ func makePointerDeserializer(fieldPath string, fieldType reflect.Type, options s
if err != nil {
err = fmt.Errorf("error in optional value at %s\n\t * %w", fieldPath, err)
slog.Error("Internal error during deserialization", "error", err)
return err
return CustomDeserializerError{
Wrapped: err,
Operation: "orMethod",
Structure: "ptr",
}
}
outPtr.Set(reflect.ValueOf(result))
return nil
Expand Down Expand Up @@ -987,7 +1036,11 @@ func makeFlatFieldDeserializer(fieldPath string, fieldType reflect.Type, options
if err != nil {
err = fmt.Errorf("error in optional value at %s\n\t * %w", fieldPath, err)
slog.Error("Internal error during deserialization", "error", err)
return err
return CustomDeserializerError{
Wrapped: err,
Operation: "orMethod",
Structure: "field",
}
}
input = constructed
default:
Expand Down
5 changes: 5 additions & 0 deletions deserialize/deserialize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package deserialize_test

import (
"encoding/json"
"errors"
"fmt"
"strings"
"testing"
Expand Down Expand Up @@ -768,6 +769,10 @@ func TestInitializerFaulty(t *testing.T) {
sample := EmptyStruct{}
_, err := twoWaysGeneric[EmptyStruct, StructInitializerFaulty](t, sample)
assert.Equal(t, err.Error(), "at StructInitializerFaulty, encountered an error while initializing optional fields:\n\t * Test error", "Initializer should have initialized our structure")

asCustom := deserialize.CustomDeserializerError{}
ok := errors.As(err, &asCustom)
assert.Equal(t, ok, true, "the error should be a CustomDeserializerError")
}

type StructUnmarshal struct {
Expand Down

0 comments on commit 15f5b2f

Please sign in to comment.