feat: add Decoder.UseNumber and the Number type
Test / test (push) Successful in 1m52s

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-21 23:49:39 +02:00
parent 582222738b
commit ce0c1ebd9d
9 changed files with 320 additions and 4 deletions
+16 -3
View File
@@ -127,11 +127,12 @@ func ParseMapContext(ctx context.Context, data []byte) (map[string]any, error) {
return tree, err
}
// parseOptions bound the work one parse may do. A zero field takes the
// default.
// parseOptions bound the work one parse may do and the shape it produces. A
// zero field takes the default.
type parseOptions struct {
maxDepth int
maxInputSize int
useNumber bool
}
// parseWithOptions parses data, building the node tree of a Document when
@@ -152,7 +153,7 @@ func parseWithOptions(ctx context.Context, data []byte, opts parseOptions, wantD
}
// The parser scans data in place; it only reads the buffer, and every
// string it stores in the tree is copied out of it.
p := &parser{src: data, line: 1, ctx: ctx, maxDepth: maxDepth, wantDoc: wantDoc}
p := &parser{src: data, line: 1, ctx: ctx, maxDepth: maxDepth, wantDoc: wantDoc, useNumber: opts.useNumber}
tree, err := p.parse()
if err != nil {
return nil, nil, err
@@ -193,6 +194,7 @@ func UnmarshalContext(ctx context.Context, data []byte, v any) error {
// strictness and configurable limits on the parse it performs.
type Decoder struct {
disallowUnknown bool
useNumber bool
maxDepth int
maxInputSize int
}
@@ -207,6 +209,16 @@ func (d *Decoder) DisallowUnknownFields() *Decoder {
return d
}
// UseNumber causes the numbers of the document to reach the value tree as a
// Number carrying the literal the document wrote, so 0x1f, 1_000, +1.0 and
// inf survive a round trip with their spelling intact. A destination of a
// concrete numeric kind still takes the evaluated value; the literal is kept
// only where a Number, or an any, receives it.
func (d *Decoder) UseNumber() *Decoder {
d.useNumber = true
return d
}
// MaxDepth bounds how deeply arrays and inline tables may nest in a document
// this decoder accepts. The parser is a recursive descent, so a document that
// nests without bound would exhaust the stack; one that nests deeper than the
@@ -242,6 +254,7 @@ func (d *Decoder) DecodeContext(ctx context.Context, data []byte, v any) error {
tree, _, err := parseWithOptions(ctx, data, parseOptions{
maxDepth: d.maxDepth,
maxInputSize: d.maxInputSize,
useNumber: d.useNumber,
}, false)
if err != nil {
return err