diff --git a/clone.go b/clone.go index ba51fdf..c516afe 100644 --- a/clone.go +++ b/clone.go @@ -12,6 +12,13 @@ const ( maxDepth = 32 ) +var ( + // ignoreTypes is a map of types that should not be redacted. It lists types that can not be copied. For example, reflect.Type is a pointer to a struct and copying it causes panic. Especially, reflect.rtype is unexported type. Then, the ignoreTypes is list of string of type name. + ignoreTypes = map[string]struct{}{ + "*reflect.rtype": {}, + } +) + func (x *masq) clone(ctx context.Context, fieldName string, src reflect.Value, tag string) reflect.Value { if v, ok := ctx.Value(ctxKeyDepth{}).(int); !ok { ctx = context.WithValue(ctx, ctxKeyDepth{}, 0) @@ -26,6 +33,9 @@ func (x *masq) clone(ctx context.Context, fieldName string, src reflect.Value, t if _, ok := x.allowedTypes[src.Type()]; ok { return src } + if _, ok := ignoreTypes[src.Type().String()]; ok { + return src + } if src.Kind() == reflect.Ptr && src.IsNil() { return reflect.New(src.Type()).Elem() @@ -58,7 +68,6 @@ func (x *masq) clone(ctx context.Context, fieldName string, src reflect.Value, t for i := 0; i < t.NumField(); i++ { f := t.Field(i) - println("f.Name", f.Name) srcValue := src.Field(i) dstValue := dst.Elem().Field(i) @@ -83,10 +92,6 @@ func (x *masq) clone(ctx context.Context, fieldName string, src reflect.Value, t } srcValue = reflect.NewAt(srcValue.Type(), unsafe.Pointer(srcValue.UnsafeAddr())).Elem() - } else if srcValue.Kind() == reflect.Func { - println("func!") - dstValue.Set(srcValue) - continue } tagValue := f.Tag.Get(x.tagKey) diff --git a/clone_test.go b/clone_test.go index 7695a73..b83de00 100644 --- a/clone_test.go +++ b/clone_test.go @@ -344,16 +344,20 @@ func TestCircularReference(t *testing.T) { gt.V(t, newData.Child.Child.Str).Equal("[REDACTED]") } -func TestCloneJsonUnmarshalTypeError(t *testing.T) { - var s string - src := json.Unmarshal([]byte(`["foo"]`), &s).(*json.UnmarshalTypeError) - dst := masq.NewMasq().Redact(src).(*json.UnmarshalTypeError) - gt.Equal(t, dst, src) -} - func TestCloneFunc(t *testing.T) { type myFunc func() string src := myFunc(func() string { return "blue" }) dst := masq.NewMasq().Redact(src).(myFunc) gt.Equal(t, dst(), "blue") } + +func TestUnmarshalTypeError(t *testing.T) { + var buf bytes.Buffer + logger := slog.New(slog.NewJSONHandler(&buf, &slog.HandlerOptions{ + ReplaceAttr: masq.New(), + })) + var s string + err := json.Unmarshal([]byte(`["foo"]`), &s) + logger.Info("error", slog.Any("err", err)) + gt.S(t, buf.String()).Contains("error") +} diff --git a/masq_test.go b/masq_test.go index d3bbf3a..ab3f201 100644 --- a/masq_test.go +++ b/masq_test.go @@ -1,10 +1,7 @@ package masq_test import ( - "encoding/json" "os" - "reflect" - "testing" "log/slog" @@ -28,19 +25,3 @@ func Example() { logger.Info("hello", slog.Any("user", u)) } - -func TestJsonUnmarshalTypeError(t *testing.T) { - // It should not panic - logger := slog.New( - slog.NewJSONHandler( - os.Stdout, - &slog.HandlerOptions{ - ReplaceAttr: masq.New(masq.WithAllowedType(reflect.TypeOf(json.UnmarshalTypeError{}))), - }, - ), - ) - var s string - err := json.Unmarshal([]byte(`["foo"]`), &s) - slog.Info("error", "err", err) - logger.Info("error", "err", err) -}