perf(decode): parse struct destinations without the value tree
Test / test (push) Successful in 1m50s
Test / test (push) Successful in 1m50s
Assisted-by: GLM 5.3 Flash
This commit is contained in:
+26
-6
@@ -305,14 +305,22 @@ func NewSchema[T any]() {
|
||||
|
||||
// UnmarshalContext is the cancellable variant of Unmarshal.
|
||||
func UnmarshalContext(ctx context.Context, data []byte, v any) error {
|
||||
dec := newDecoder()
|
||||
dec.ctx = ctx
|
||||
if canTargetDecode(v) {
|
||||
// The targeted parse fills struct destinations without the
|
||||
// intermediate tree; a document or destination it cannot model falls
|
||||
// back to the tree path, whose contracts it keeps.
|
||||
if err := parseIntoTargeted(ctx, data, dec, false, 0, v); err != errTargetFallback {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Only a destination that can reach an OrderedMap needs the node tree the
|
||||
// written key order is read from; every other decode skips building it.
|
||||
tree, doc, err := parseWithOptions(ctx, data, parseOptions{}, typeWantsOrder(reflect.TypeOf(v)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dec := newDecoder()
|
||||
dec.ctx = ctx
|
||||
dec.nodes = indexNodes(doc.Root())
|
||||
return dec.decode(tree, v)
|
||||
}
|
||||
@@ -390,6 +398,22 @@ func (d *Decoder) Decode(data []byte, v any) error {
|
||||
|
||||
// DecodeContext is the cancellable variant of Decode.
|
||||
func (d *Decoder) DecodeContext(ctx context.Context, data []byte, v any) error {
|
||||
dec := newDecoder()
|
||||
dec.disallowUnknown = d.disallowUnknown
|
||||
dec.ctx = ctx
|
||||
dec.loc = d.localLoc
|
||||
if canTargetDecode(v) {
|
||||
// The targeted parse fills struct destinations without the
|
||||
// intermediate tree; a document or destination it cannot model falls
|
||||
// back to the tree path, whose contracts it keeps. The size limit is
|
||||
// checked here, the targeted parse being the parse itself.
|
||||
if d.maxInputSize > 0 && len(data) > d.maxInputSize {
|
||||
return fmt.Errorf("interpres: input is %d bytes, over the limit of %d", len(data), d.maxInputSize)
|
||||
}
|
||||
if err := parseIntoTargeted(ctx, data, dec, d.useNumber, d.maxDepth, v); err != errTargetFallback {
|
||||
return err
|
||||
}
|
||||
}
|
||||
opts := parseOptions{
|
||||
maxDepth: d.maxDepth,
|
||||
maxInputSize: d.maxInputSize,
|
||||
@@ -399,11 +423,7 @@ func (d *Decoder) DecodeContext(ctx context.Context, data []byte, v any) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dec := newDecoder()
|
||||
dec.disallowUnknown = d.disallowUnknown
|
||||
dec.ctx = ctx
|
||||
dec.nodes = indexNodes(doc.Root())
|
||||
dec.loc = d.localLoc
|
||||
return dec.decode(tree, v)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user