feat: typed decode and encode errors with the key path

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-17 21:20:47 +02:00
parent 1e3198c8b6
commit 3f41266710
7 changed files with 219 additions and 18 deletions
+8 -7
View File
@@ -6,6 +6,7 @@ package interpres
import (
"bytes"
"context"
"errors"
"fmt"
"maps"
"math"
@@ -287,7 +288,7 @@ func addField(doc *tomlDoc, name string, v reflect.Value, ctx string) error {
if m, ok := v.Interface().(Marshaler); ok {
mv, err := m.MarshalTOML()
if err != nil {
return fmt.Errorf("interpres: %s.%s: %w", ctx, name, err)
return &EncodeError{Path: joinKey(ctx, name), Err: err}
}
v = reflect.ValueOf(mv)
}
@@ -380,13 +381,13 @@ func addArrayValue(doc *tomlDoc, name string, v reflect.Value, ctx string) error
}
ev := followPtr(v.Index(i))
if !ev.IsValid() {
return fmt.Errorf("interpres: %s.%s[%d]: nil element", ctx, name, i)
return &EncodeError{Path: fmt.Sprintf("%s[%d]", joinKey(ctx, name), i), Err: errors.New("nil element")}
}
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts}
switch ev.Kind() {
case reflect.Struct:
if isScalarStruct(ev.Type()) {
return fmt.Errorf("interpres: %s.%s[%d]: heterogeneous array contains scalar", ctx, name, i)
return &EncodeError{Path: fmt.Sprintf("%s[%d]", joinKey(ctx, name), i), Err: errors.New("heterogeneous array contains scalar")}
}
if err := buildStructDoc(ev, sub, joinKey(ctx, fmt.Sprintf("%s[%d]", name, i))); err != nil {
return err
@@ -396,7 +397,7 @@ func addArrayValue(doc *tomlDoc, name string, v reflect.Value, ctx string) error
return err
}
default:
return fmt.Errorf("interpres: %s.%s: heterogeneous array, expected table", ctx, name)
return &EncodeError{Path: joinKey(ctx, name), Err: errors.New("heterogeneous array, expected table")}
}
subs[i] = sub
}
@@ -415,13 +416,13 @@ func addArrayValue(doc *tomlDoc, name string, v reflect.Value, ctx string) error
}
ev := followPtr(v.Index(i))
if !ev.IsValid() {
return fmt.Errorf("interpres: %s.%s[%d]: nil element", ctx, name, i)
return &EncodeError{Path: fmt.Sprintf("%s[%d]", joinKey(ctx, name), i), Err: errors.New("nil element")}
}
if ev.CanInterface() {
if m, ok := ev.Interface().(Marshaler); ok {
mv, err := m.MarshalTOML()
if err != nil {
return fmt.Errorf("interpres: %s.%s[%d]: %w", ctx, name, i, err)
return &EncodeError{Path: fmt.Sprintf("%s[%d]", joinKey(ctx, name), i), Err: err}
}
ev = reflect.ValueOf(mv)
ev = followPtr(ev)
@@ -429,7 +430,7 @@ func addArrayValue(doc *tomlDoc, name string, v reflect.Value, ctx string) error
}
val, err := normaliseValue(ev)
if err != nil {
return fmt.Errorf("interpres: %s.%s[%d]: %w", ctx, name, i, err)
return &EncodeError{Path: fmt.Sprintf("%s[%d]", joinKey(ctx, name), i), Err: err}
}
items[i] = val
}