v0.1.3 bound parse memory and errors, conform better to toml spec for escpae and control chars
Test / test (push) Canceled after 0s

This commit is contained in:
lixen committed 2026-10-03 23:14:11 -04:00
1 parent cede215365
commit 18ae215998
8 files changed
+283 -40

No files matched your search

+30 -3
View File
@@ -40,6 +40,33 @@ func decodeValue(data any, val reflect.Value) error {
return decodeAt(data, val, 0)
}
// pathError names where decoding failed. Each level adds its segment instead
// of wrapping the message, which would copy the message once per level.
type pathError struct {
path []string // innermost first
err error
}
func (e *pathError) Error() string {
var b strings.Builder
for i := len(e.path) - 1; i >= 0; i-- {
b.WriteString(e.path[i])
b.WriteString(": ")
}
b.WriteString(e.err.Error())
return b.String()
}
func (e *pathError) Unwrap() error { return e.err }
func atPath(segment string, err error) error {
if pe, ok := err.(*pathError); ok {
pe.path = append(pe.path, segment)
return pe
}
return &pathError{path: []string{segment}, err: err}
}
func decodeAt(data any, val reflect.Value, depth int) error {
if depth > maxValueDepth {
return fmt.Errorf("decode nesting exceeds %d", maxValueDepth)
@@ -91,7 +118,7 @@ func decodeAt(data any, val reflect.Value, depth int) error {
}
for i := 0; i < len(dataSlice); i++ {
if err := decodeAt(dataSlice[i], newSlice.Index(i), depth+1); err != nil {
return fmt.Errorf("index %d: %w", i, err)
return atPath(fmt.Sprintf("index %d", i), err)
}
}
val.Set(newSlice)
@@ -109,7 +136,7 @@ func decodeAt(data any, val reflect.Value, depth int) error {
for k, vData := range dataMap {
newVal := reflect.New(elemType).Elem()
if err := decodeAt(vData, newVal, depth+1); err != nil {
return fmt.Errorf("map key %s: %w", k, err)
return atPath("map key "+brief(k), err)
}
newMap.SetMapIndex(reflect.ValueOf(k).Convert(val.Type().Key()), newVal)
}
@@ -206,7 +233,7 @@ func decodeStruct(data map[string]any, val reflect.Value, depth int) error {
// Look up in data map (case sensitive)
if vData, ok := data[key]; ok {
if err := decodeAt(vData, field, depth+1); err != nil {
return fmt.Errorf("%s.%s: %w", typ.Name(), fieldType.Name, err)
return atPath(typ.Name()+"."+fieldType.Name, err)
}
}
}