Assisted-by: GLM 5.3 Flash
This commit is contained in:
@@ -247,7 +247,10 @@ func buildOrderedDoc(om *OrderedMap, doc *tomlDoc, path encPath) error {
|
||||
val := om.values[key]
|
||||
switch x := val.(type) {
|
||||
case OrderedMap:
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts}
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts, depth: doc.depth + 1}
|
||||
if atDepthLimit(sub.depth) {
|
||||
return &EncodeError{Path: path.key(key).String(), Err: errDepthLimit()}
|
||||
}
|
||||
if err := buildOrderedDoc(&x, sub, path.key(key)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -257,7 +260,10 @@ func buildOrderedDoc(om *OrderedMap, doc *tomlDoc, path encPath) error {
|
||||
if x == nil {
|
||||
continue
|
||||
}
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts}
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts, depth: doc.depth + 1}
|
||||
if atDepthLimit(sub.depth) {
|
||||
return &EncodeError{Path: path.key(key).String(), Err: errDepthLimit()}
|
||||
}
|
||||
if err := buildOrderedDoc(x, sub, path.key(key)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -304,11 +310,30 @@ type entry struct {
|
||||
emitted bool
|
||||
}
|
||||
|
||||
// tomlDoc holds the entries of one TOML table in declaration order.
|
||||
// tomlDoc holds the entries of one TOML table in declaration order. depth is
|
||||
// the nesting level the table sits at, which bounds the walk: cyclic data
|
||||
// would recurse forever, and hits the limit instead of the stack.
|
||||
type tomlDoc struct {
|
||||
entries []entry
|
||||
ctx context.Context // inherited from encoder; nil-safe
|
||||
opts Encoder // inherited from encoder; options drive emit-time behaviour
|
||||
depth int
|
||||
}
|
||||
|
||||
// maxEncodeDepth bounds the encoding walk. It matches the parser's nesting
|
||||
// limit: a document that deep cannot be written by this encoder either, and
|
||||
// a value that nests that far without being an array or a table is cyclic.
|
||||
const maxEncodeDepth = maxNestingDepth
|
||||
|
||||
// atDepthLimit reports whether a table nested depth levels is past the walk's
|
||||
// limit.
|
||||
func atDepthLimit(depth int) bool {
|
||||
return depth > maxEncodeDepth
|
||||
}
|
||||
|
||||
// errDepthLimit is the failure a cyclic value walks into.
|
||||
func errDepthLimit() error {
|
||||
return fmt.Errorf("value nests deeper than the limit of %d levels; the value may be cyclic", maxEncodeDepth)
|
||||
}
|
||||
|
||||
func (d *tomlDoc) checkCtx() error {
|
||||
@@ -385,7 +410,7 @@ func (p encPath) String() string {
|
||||
// --- reflection walk: struct ---------------------------------------------
|
||||
|
||||
func buildStructDoc(v reflect.Value, doc *tomlDoc, path encPath) error {
|
||||
return walkStructDoc(v, doc, path, nil, cachedStructSchema(v.Type()))
|
||||
return walkStructDoc(v, doc, path, nil, cachedStructSchema(v.Type()), doc.depth)
|
||||
}
|
||||
|
||||
// walkStructDoc emits the fields of v into doc. prefix is v's index path from
|
||||
@@ -393,8 +418,13 @@ func buildStructDoc(v reflect.Value, doc *tomlDoc, path encPath) error {
|
||||
// with the outer schema and a longer prefix, so every leaf competes under the
|
||||
// decoder's rule: the shallower field wins, the later declaration at equal
|
||||
// depth. A field another field shadows is skipped, because emitting both
|
||||
// would duplicate the key and the output would not re-parse.
|
||||
func walkStructDoc(v reflect.Value, doc *tomlDoc, path encPath, prefix []int, schema structSchema) error {
|
||||
// would duplicate the key and the output would not re-parse. depth is the
|
||||
// nesting the walk has reached, which an embedded struct raises; a cycle
|
||||
// through embedded pointers ends at the limit instead of the stack.
|
||||
func walkStructDoc(v reflect.Value, doc *tomlDoc, path encPath, prefix []int, schema structSchema, depth int) error {
|
||||
if atDepthLimit(depth) {
|
||||
return fmt.Errorf("interpres: %s: %w", path.String(), errDepthLimit())
|
||||
}
|
||||
t := v.Type()
|
||||
if cap(doc.entries) == 0 {
|
||||
doc.entries = make([]entry, 0, t.NumField())
|
||||
@@ -430,7 +460,7 @@ func walkStructDoc(v reflect.Value, doc *tomlDoc, path encPath, prefix []int, sc
|
||||
doc.addScalar(name, fv.Interface())
|
||||
continue
|
||||
}
|
||||
if err := walkStructDoc(fv, doc, path, fpath, schema); err != nil {
|
||||
if err := walkStructDoc(fv, doc, path, fpath, schema, depth+1); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
@@ -520,6 +550,9 @@ func fieldName(f reflect.StructField) string {
|
||||
// --- reflection walk: map ------------------------------------------------
|
||||
|
||||
func buildMapDoc(v reflect.Value, doc *tomlDoc, path encPath) error {
|
||||
if atDepthLimit(doc.depth) {
|
||||
return fmt.Errorf("interpres: %s: %w", path.String(), errDepthLimit())
|
||||
}
|
||||
if v.Type().Key().Kind() != reflect.String {
|
||||
return fmt.Errorf("interpres: map key must be string, got %s", v.Type().Key())
|
||||
}
|
||||
@@ -584,7 +617,10 @@ func addField(doc *tomlDoc, name string, v reflect.Value, path encPath) error {
|
||||
}
|
||||
if v.Type() == orderedMapType {
|
||||
om := v.Interface().(OrderedMap)
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts}
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts, depth: doc.depth + 1}
|
||||
if atDepthLimit(sub.depth) {
|
||||
return &EncodeError{Path: path.key(name).String(), Err: errDepthLimit()}
|
||||
}
|
||||
if err := buildOrderedDoc(&om, sub, path.key(name)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -613,7 +649,10 @@ func addField(doc *tomlDoc, name string, v reflect.Value, path encPath) error {
|
||||
}
|
||||
|
||||
func addSubTable(doc *tomlDoc, name string, v reflect.Value, path encPath) error {
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts}
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts, depth: doc.depth + 1}
|
||||
if atDepthLimit(sub.depth) {
|
||||
return &EncodeError{Path: path.key(name).String(), Err: errDepthLimit()}
|
||||
}
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
if err := buildStructDoc(v, sub, path.key(name)); err != nil {
|
||||
@@ -692,7 +731,10 @@ func addArrayValue(doc *tomlDoc, name string, v reflect.Value, path encPath) err
|
||||
return err
|
||||
}
|
||||
}
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts}
|
||||
sub := &tomlDoc{ctx: doc.ctx, opts: doc.opts, depth: doc.depth + 1}
|
||||
if atDepthLimit(sub.depth) {
|
||||
return &EncodeError{Path: apath.elem(i).String(), Err: errDepthLimit()}
|
||||
}
|
||||
switch {
|
||||
case ev.Type() == orderedMapType:
|
||||
om := ev.Interface().(OrderedMap)
|
||||
@@ -795,6 +837,13 @@ func resolveElement(v reflect.Value, path encPath) (reflect.Value, error) {
|
||||
// nested-array representations the emitter understands. Slices and arrays are
|
||||
// recursively normalised so that nested arrays (e.g. [][]int) work.
|
||||
func normaliseValue(v reflect.Value) (any, error) {
|
||||
return normaliseValueAt(v, 0)
|
||||
}
|
||||
|
||||
func normaliseValueAt(v reflect.Value, depth int) (any, error) {
|
||||
if atDepthLimit(depth) {
|
||||
return nil, errDepthLimit()
|
||||
}
|
||||
if !v.IsValid() {
|
||||
return nil, fmt.Errorf("cannot encode nil value")
|
||||
}
|
||||
@@ -818,7 +867,7 @@ func normaliseValue(v reflect.Value) (any, error) {
|
||||
// receiver's own type is written as it is, because recursing into it
|
||||
// would never end.
|
||||
if rv := reflect.ValueOf(mv); rv.Type() != v.Type() {
|
||||
return normaliseValue(rv)
|
||||
return normaliseValueAt(rv, depth+1)
|
||||
}
|
||||
return mv, nil
|
||||
}
|
||||
@@ -842,7 +891,7 @@ func normaliseValue(v reflect.Value) (any, error) {
|
||||
om := v.Interface().(OrderedMap)
|
||||
out := make(map[string]any, om.Len())
|
||||
for _, k := range om.Keys() {
|
||||
val, err := normaliseValue(reflect.ValueOf(om.values[k]))
|
||||
val, err := normaliseValueAt(reflect.ValueOf(om.values[k]), depth+1)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[%s]: %w", k, err)
|
||||
}
|
||||
@@ -882,7 +931,7 @@ func normaliseValue(v reflect.Value) (any, error) {
|
||||
}
|
||||
out := make(map[string]any, v.Len())
|
||||
for _, k := range v.MapKeys() {
|
||||
val, err := normaliseValue(v.MapIndex(k))
|
||||
val, err := normaliseValueAt(v.MapIndex(k), depth+1)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[%s]: %w", k.String(), err)
|
||||
}
|
||||
@@ -892,7 +941,7 @@ func normaliseValue(v reflect.Value) (any, error) {
|
||||
case reflect.Slice, reflect.Array:
|
||||
items := make([]any, v.Len())
|
||||
for i := range v.Len() {
|
||||
val, err := normaliseValue(v.Index(i))
|
||||
val, err := normaliseValueAt(v.Index(i), depth+1)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[%d]: %w", i, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user