qubit_json/decode/json_decoder.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Stateful strict JSON decoding with caller-owned resource accounting.
9
10use qubit_budget::ResourceQuantity;
11use qubit_budget::json::JsonDecodeLimits;
12use qubit_budget::json::JsonDecodeSession;
13use qubit_budget::json::JsonResource;
14use qubit_io::ByteInput;
15use qubit_io::Input;
16use serde::Deserialize;
17use serde::de::DeserializeOwned;
18use serde::de::DeserializeSeed;
19
20use super::DiagnosticPolicy;
21use super::JsonDecodeError;
22use super::JsonDecodeNumberModel;
23use super::JsonNumberPolicy;
24use super::JsonNumberToken;
25use super::JsonPathSegment;
26use super::JsonRootKind;
27use super::JsonValidatedDecodeError;
28use super::JsonValidatedDecodeOptions;
29use super::internal::JsonDecodeEngine;
30use super::internal::TypedSeed;
31use crate::value::SafeJsonValue;
32
33/// Strictly decodes complete JSON documents while retaining cumulative usage.
34///
35/// This facade performs no normalization. It accepts integers from `i64::MIN`
36/// through `u64::MAX`, requires finite floating-point values, supports values
37/// borrowing from its input, and exposes caller-provided Serde seeds.
38///
39/// # Type Parameters
40///
41/// * `'budget` - Lifetime of the resource budget borrowed by the decoder's
42/// cumulative session.
43/// * `R` - Resource identity type tracked by the session.
44/// * `Q` - Quantity type used for resource limits and accounting.
45///
46/// # Examples
47///
48/// ```
49/// use qubit_json::decode::JsonDecoder;
50/// use serde_json::Value;
51///
52/// let mut decoder = JsonDecoder::unlimited();
53/// let value = decoder.decode_str::<Value>(r#"{"ok":true}"#)?;
54/// assert_eq!(value["ok"], true);
55/// # Ok::<(), qubit_json::decode::JsonDecodeError>(())
56/// ```
57#[derive(Debug)]
58pub struct JsonDecoder<'budget, R = JsonResource, Q = usize>
59where
60 Q: ResourceQuantity,
61{
62 /// Diagnostic detail retained for input-derived failures.
63 diagnostic_policy: DiagnosticPolicy,
64 /// Shared generic decoding and accounting core.
65 engine: JsonDecodeEngine<'budget, R, Q>,
66}
67
68impl<R, Q> JsonDecoder<'static, R, Q>
69where
70 R: Clone,
71 Q: ResourceQuantity,
72{
73 /// Creates a decoder with a cumulative session built from explicit limits.
74 ///
75 /// # Parameters
76 ///
77 /// * `limits` - Input and decoded-value limits used by the cumulative
78 /// session.
79 ///
80 /// # Returns
81 ///
82 /// A decoder whose accounting starts empty and is constrained by `limits`.
83 #[inline(always)]
84 #[must_use]
85 pub fn with_limits(limits: JsonDecodeLimits<R, Q>) -> Self {
86 Self::new(JsonDecodeSession::from_limits(limits))
87 }
88}
89
90impl JsonDecoder<'static, JsonResource, usize> {
91 /// Creates a decoder with no configured input or value limits.
92 ///
93 /// # Returns
94 ///
95 /// A decoder using the standard resource identities with all limits
96 /// disabled.
97 #[inline(always)]
98 #[must_use]
99 pub fn unlimited() -> Self {
100 Self::with_limits(JsonDecodeLimits::new())
101 }
102}
103
104impl<'budget, R, Q> JsonDecoder<'budget, R, Q>
105where
106 R: Clone,
107 Q: ResourceQuantity,
108{
109 /// Creates a strict decoder around a reusable cumulative session.
110 ///
111 /// # Parameters
112 ///
113 /// * `session` - Cumulative session that receives input and decoded-value
114 /// charges.
115 ///
116 /// # Returns
117 ///
118 /// A decoder that owns `session` until it is consumed by
119 /// [`Self::into_session`].
120 #[inline]
121 #[must_use]
122 pub const fn new(session: JsonDecodeSession<'budget, R, Q>) -> Self {
123 Self {
124 diagnostic_policy: DiagnosticPolicy::Redacted,
125 engine: JsonDecodeEngine::new(session),
126 }
127 }
128
129 /// Decodes one complete document into a guarded value and rejects duplicate
130 /// keys.
131 ///
132 /// # Parameters
133 ///
134 /// * `input` - Complete UTF-8 JSON document.
135 ///
136 /// # Returns
137 ///
138 /// The protected owned value after input and value accounting succeed.
139 ///
140 /// # Errors
141 ///
142 /// Returns a structured error for invalid UTF-8, syntax, numeric range,
143 /// duplicate keys, or configured resource limits.
144 pub fn decode_value_utf8(
145 &mut self,
146 input: &[u8],
147 ) -> Result<SafeJsonValue, JsonDecodeError<R, Q>> {
148 self.engine.decode_value_utf8(input, self.diagnostic_policy)
149 }
150
151 /// UTF-8 string form of [`Self::decode_value_utf8`].
152 ///
153 /// # Parameters
154 ///
155 /// * `input` - Complete JSON document text.
156 ///
157 /// # Returns
158 ///
159 /// The protected owned value.
160 ///
161 /// # Errors
162 ///
163 /// Returns a structured error for syntax, numeric range, duplicate keys,
164 /// or configured resource limits.
165 pub fn decode_value_str(
166 &mut self,
167 input: &str,
168 ) -> Result<SafeJsonValue, JsonDecodeError<R, Q>> {
169 self.decode_value_utf8(input.as_bytes())
170 }
171
172 /// Reads one unique-key document through EOF and decodes it into a guarded
173 /// value.
174 ///
175 /// Reads in bounded chunks, with at most one probe byte beyond an active
176 /// input limit. Accepted bytes remain charged when later validation fails.
177 ///
178 /// # Parameters
179 ///
180 /// * `input` - Byte input read through EOF.
181 ///
182 /// # Type Parameters
183 ///
184 /// * `I` - Byte input type that supplies the complete document.
185 ///
186 /// # Returns
187 ///
188 /// The protected owned value.
189 ///
190 /// # Errors
191 ///
192 /// Returns read, input-budget, UTF-8, syntax, numeric-range, duplicate-key,
193 /// or value-budget failures.
194 pub fn decode_value_input<I: ByteInput + ?Sized>(
195 &mut self,
196 input: &mut I,
197 ) -> Result<SafeJsonValue, JsonDecodeError<R, Q>> {
198 self.engine
199 .decode_value_input(input, self.diagnostic_policy)
200 }
201
202 /// Decodes one document while applying a caller policy to each source
203 /// number.
204 ///
205 /// The callback runs in source order after a number token is syntactically
206 /// complete and before its configured representation range is checked. It
207 /// receives the typed path and borrowed source spelling; its first error
208 /// stops scanning immediately. Object keys must be unique after decoding.
209 /// Side effects performed by the callback are not rolled back if later
210 /// syntax, delimiter, or budget validation fails. The string and input
211 /// forms of this method have the same callback contract.
212 ///
213 /// ```
214 /// use std::cell::Cell;
215 /// use std::convert::Infallible;
216 /// use qubit_json::decode::JsonDecoder;
217 /// use qubit_json::decode::JsonNumberPolicy;
218 /// use qubit_json::decode::JsonValidatedDecodeOptions;
219 ///
220 /// let calls = Cell::new(0);
221 /// let result = JsonDecoder::unlimited().decode_unique_validated_str(
222 /// "[1,]",
223 /// &JsonValidatedDecodeOptions::builder().build(),
224 /// |_, _| {
225 /// calls.set(calls.get() + 1);
226 /// Ok::<_, Infallible>(JsonNumberPolicy::Preserve)
227 /// },
228 /// );
229 /// assert!(result.is_err());
230 /// assert_eq!(calls.get(), 1);
231 /// ```
232 ///
233 /// # Parameters
234 ///
235 /// * `input` - Complete UTF-8 JSON document.
236 /// * `options` - Root, number model, and per-document source-token limits.
237 /// * `number_policy` - Synchronous policy called for each complete number.
238 ///
239 /// # Type Parameters
240 ///
241 /// * `E` - Error type returned by the caller's number policy.
242 /// * `F` - Number policy callback type.
243 ///
244 /// # Returns
245 ///
246 /// The protected owned value after complete scanning and accounting.
247 ///
248 /// # Errors
249 ///
250 /// Returns structured decode errors, callback errors with source offsets,
251 /// exact-safe-integer errors, or validated-limit failures.
252 pub fn decode_unique_validated_utf8<E, F>(
253 &mut self,
254 input: &[u8],
255 options: &JsonValidatedDecodeOptions,
256 number_policy: F,
257 ) -> Result<SafeJsonValue, JsonValidatedDecodeError<E, R, Q>>
258 where
259 F: for<'call> FnMut(
260 &'call [JsonPathSegment],
261 JsonNumberToken<'call>,
262 ) -> Result<JsonNumberPolicy, E>,
263 {
264 self.engine.decode_unique_validated_utf8(
265 input,
266 options,
267 number_policy,
268 self.diagnostic_policy,
269 )
270 }
271
272 /// UTF-8 string form of [`Self::decode_unique_validated_utf8`], with the
273 /// same callback side-effect contract documented there.
274 ///
275 /// # Parameters
276 ///
277 /// * `input` - Complete JSON document text.
278 /// * `options` - Root, number model, and per-document source-token limits.
279 /// * `number_policy` - Synchronous number policy callback.
280 ///
281 /// # Type Parameters
282 ///
283 /// * `E` - Error type returned by the caller's number policy.
284 /// * `F` - Number policy callback type.
285 ///
286 /// # Returns
287 ///
288 /// The protected owned value.
289 ///
290 /// # Errors
291 ///
292 /// Returns decode, callback, exact-safe-integer, or validated-limit errors.
293 pub fn decode_unique_validated_str<E, F>(
294 &mut self,
295 input: &str,
296 options: &JsonValidatedDecodeOptions,
297 number_policy: F,
298 ) -> Result<SafeJsonValue, JsonValidatedDecodeError<E, R, Q>>
299 where
300 F: for<'call> FnMut(
301 &'call [JsonPathSegment],
302 JsonNumberToken<'call>,
303 ) -> Result<JsonNumberPolicy, E>,
304 {
305 self.decode_unique_validated_utf8(input.as_bytes(), options, number_policy)
306 }
307
308 /// Reads a byte input through EOF and applies a source-number policy during
309 /// decoding.
310 ///
311 /// Accepted input bytes remain charged if the callback or later validation
312 /// fails; value charges commit only after the complete document succeeds.
313 /// Callback side effects are not rolled back on failure, as documented for
314 /// [`Self::decode_unique_validated_utf8`].
315 ///
316 /// # Parameters
317 ///
318 /// * `input` - Byte input read through EOF.
319 /// * `options` - Root, number model, and per-document token limits.
320 /// * `number_policy` - Synchronous callback for each source number.
321 ///
322 /// # Type Parameters
323 ///
324 /// * `E` - Error type returned by the caller's number policy.
325 /// * `F` - Number policy callback type.
326 /// * `I` - Byte input type that supplies the complete document.
327 ///
328 /// # Returns
329 ///
330 /// The protected owned value.
331 ///
332 /// # Errors
333 ///
334 /// Returns structured decode, read, callback, exact-integer, or limit
335 /// errors.
336 pub fn decode_unique_validated_input<E, F, I>(
337 &mut self,
338 input: &mut I,
339 options: &JsonValidatedDecodeOptions,
340 number_policy: F,
341 ) -> Result<SafeJsonValue, JsonValidatedDecodeError<E, R, Q>>
342 where
343 I: ByteInput + ?Sized,
344 F: for<'call> FnMut(
345 &'call [JsonPathSegment],
346 JsonNumberToken<'call>,
347 ) -> Result<JsonNumberPolicy, E>,
348 {
349 self.engine.decode_unique_validated_input(
350 input,
351 options,
352 number_policy,
353 self.diagnostic_policy,
354 )
355 }
356
357 /// Decodes one byte input using an explicit integer/fallback number model.
358 ///
359 /// The number model controls whether an integer token outside `i64`/`u64`
360 /// is admitted. With the fallback model, that token is admitted only when
361 /// it converts to finite `f64`. Decimal and exponent forms use the
362 /// finite-float rule in both models.
363 ///
364 /// The resulting representation is produced by Serde for `T` and can
365 /// depend on the active `serde_json` features. For deterministic numeric
366 /// projection, use validated decoding with `JsonNumberPolicy::Preserve`;
367 /// it materializes fallback integers as finite `f64` values.
368 ///
369 /// # Parameters
370 ///
371 /// * `input` - Byte input read through EOF.
372 /// * `model` - Integer representation model for admitted source numbers.
373 ///
374 /// # Type Parameters
375 ///
376 /// * `T` - Owned target type deserialized from the document.
377 /// * `I` - Byte input type that supplies the complete document.
378 ///
379 /// # Returns
380 ///
381 /// The owned value produced by Serde. Its numeric representation follows
382 /// `T` and the active Serde implementation and features.
383 ///
384 /// # Errors
385 ///
386 /// Returns read, UTF-8, syntax, numeric-range, budget, or Serde errors.
387 pub fn decode_input_with_number_model<T, I>(
388 &mut self,
389 input: &mut I,
390 model: JsonDecodeNumberModel,
391 ) -> Result<T, JsonDecodeError<R, Q>>
392 where
393 T: DeserializeOwned,
394 I: ByteInput + ?Sized,
395 {
396 let model = match model {
397 JsonDecodeNumberModel::Integer64 => crate::lexical::JsonNumberModel::Integer64,
398 JsonDecodeNumberModel::Integer64WithFiniteFallback => {
399 crate::lexical::JsonNumberModel::Integer64WithFiniteFallback
400 }
401 };
402 self.engine
403 .decode_input_seed(TypedSeed::new(), input, self.diagnostic_policy, model)
404 }
405
406 /// Returns the configured diagnostic policy without changing the decoder.
407 ///
408 /// # Returns
409 ///
410 /// The policy used when constructing input-derived decode errors.
411 #[inline(always)]
412 #[must_use]
413 pub const fn diagnostic_policy(&self) -> DiagnosticPolicy {
414 self.diagnostic_policy
415 }
416
417 /// Returns the cumulative session for read-only inspection.
418 ///
419 /// The returned reference is borrowed from the decoder and exposes the
420 /// charges accumulated by completed operations.
421 ///
422 /// # Returns
423 ///
424 /// A shared reference to the decoder's cumulative session.
425 #[inline(always)]
426 #[must_use]
427 pub const fn session(&self) -> &JsonDecodeSession<'budget, R, Q> {
428 self.engine.session()
429 }
430
431 /// Returns mutable access to the cumulative session.
432 ///
433 /// Mutating the session changes the limits and accounting state used by
434 /// subsequent operations.
435 ///
436 /// # Returns
437 ///
438 /// A mutable reference tied to the decoder's lifetime.
439 #[inline(always)]
440 #[must_use]
441 pub const fn session_mut(&mut self) -> &mut JsonDecodeSession<'budget, R, Q> {
442 self.engine.session_mut()
443 }
444
445 /// Configures whether input-derived error sources are retained.
446 ///
447 /// The default is [`DiagnosticPolicy::Redacted`]. Selecting
448 /// [`DiagnosticPolicy::Detailed`] may retain source errors containing
449 /// fragments or structural details derived from the input.
450 ///
451 /// # Parameters
452 ///
453 /// * `policy` - Diagnostic retention policy for failures produced by this
454 /// decoder.
455 ///
456 /// # Returns
457 ///
458 /// The decoder with the requested policy; its existing session is retained.
459 #[inline(always)]
460 #[must_use]
461 pub const fn with_diagnostic_policy(mut self, policy: DiagnosticPolicy) -> Self {
462 self.diagnostic_policy = policy;
463 self
464 }
465
466 /// Consumes the decoder and returns its cumulative session.
467 ///
468 /// This transfers ownership of all accumulated accounting state without
469 /// performing another decode or resetting the session.
470 ///
471 /// # Returns
472 ///
473 /// The session previously owned by this decoder.
474 #[inline(always)]
475 #[must_use]
476 pub fn into_session(self) -> JsonDecodeSession<'budget, R, Q> {
477 self.engine.into_session()
478 }
479
480 /// Decodes one complete JSON string and permits results borrowing `input`.
481 ///
482 /// # Type Parameters
483 ///
484 /// * `T` - Target type deserialized from the complete document.
485 ///
486 /// # Parameters
487 ///
488 /// * `input` - UTF-8 JSON text. The returned value may borrow from it.
489 ///
490 /// # Returns
491 ///
492 /// The deserialized value on success.
493 ///
494 /// # Errors
495 ///
496 /// Returns a structured error when input accounting, UTF-8 validation,
497 /// JSON parsing, or Serde deserialization fails.
498 pub fn decode_str<'de, T>(&mut self, input: &'de str) -> Result<T, JsonDecodeError<R, Q>>
499 where
500 T: Deserialize<'de>,
501 {
502 self.decode_seed_str(TypedSeed::new(), input)
503 }
504
505 /// Decodes one complete UTF-8 JSON byte slice and permits borrowed results.
506 ///
507 /// # Type Parameters
508 ///
509 /// * `T` - Target type deserialized from the complete document.
510 ///
511 /// # Parameters
512 ///
513 /// * `input` - Complete UTF-8 JSON bytes. The returned value may borrow
514 /// from this slice.
515 ///
516 /// # Returns
517 ///
518 /// The deserialized value on success.
519 ///
520 /// # Errors
521 ///
522 /// Returns a structured error when accounting, UTF-8 validation, JSON
523 /// parsing, or Serde deserialization fails.
524 pub fn decode_utf8<'de, T>(&mut self, input: &'de [u8]) -> Result<T, JsonDecodeError<R, Q>>
525 where
526 T: Deserialize<'de>,
527 {
528 self.decode_seed_utf8(TypedSeed::new(), input)
529 }
530
531 /// Decodes a complete document from an item-oriented byte input through
532 /// EOF.
533 ///
534 /// Without an input-byte limit, the input is read in fixed-size chunks.
535 /// With a limit, each read is bounded by the remaining allowance plus at
536 /// most one probe byte. The probe distinguishes an input ending exactly
537 /// at the limit from an oversized input; it is neither charged nor
538 /// buffered, and cannot be returned to the input source. The complete
539 /// admitted document is buffered in memory because the returned value
540 /// must not borrow from the temporary buffer. Without an input-byte
541 /// limit, this buffering has no implicit size cap.
542 ///
543 /// # Parameters
544 ///
545 /// * `input` - Mutable byte input read through EOF.
546 ///
547 /// # Returns
548 ///
549 /// The owned value deserialized from the complete document.
550 ///
551 /// # Errors
552 ///
553 /// Returns a structured error for read failures, input-budget rejection,
554 /// invalid UTF-8, invalid JSON, or target deserialization failures.
555 ///
556 /// # Type Parameters
557 ///
558 /// * `T` - Owned target type deserialized from the document.
559 /// * `I` - Item-oriented byte input type that supplies the document.
560 pub fn decode_input<T, I>(&mut self, input: &mut I) -> Result<T, JsonDecodeError<R, Q>>
561 where
562 T: DeserializeOwned,
563 I: Input<Item = u8> + ?Sized,
564 {
565 self.engine.decode_input(input, self.diagnostic_policy)
566 }
567
568 /// Decodes a JSON string through a caller-provided Serde seed.
569 ///
570 /// # Type Parameters
571 ///
572 /// * `S` - Seed controlling construction of the decoded value.
573 ///
574 /// # Parameters
575 ///
576 /// * `seed` - Serde seed used to deserialize the document.
577 /// * `input` - Complete JSON text, which the seed may borrow from.
578 ///
579 /// # Returns
580 ///
581 /// The value produced by `seed`.
582 ///
583 /// # Errors
584 ///
585 /// Returns a structured error when accounting, parsing, or seeded
586 /// deserialization fails.
587 pub fn decode_seed_str<'de, S>(
588 &mut self,
589 seed: S,
590 input: &'de str,
591 ) -> Result<S::Value, JsonDecodeError<R, Q>>
592 where
593 S: DeserializeSeed<'de>,
594 {
595 self.decode_seed_utf8(seed, input.as_bytes())
596 }
597
598 /// Decodes a UTF-8 byte slice through a caller-provided Serde seed.
599 ///
600 /// # Type Parameters
601 ///
602 /// * `S` - Seed controlling construction of the decoded value.
603 ///
604 /// # Parameters
605 ///
606 /// * `seed` - Serde seed used to deserialize the document.
607 /// * `input` - Complete UTF-8 JSON bytes, which the seed may borrow from.
608 ///
609 /// # Returns
610 ///
611 /// The value produced by `seed`.
612 ///
613 /// # Errors
614 ///
615 /// Returns a structured error when accounting, UTF-8 validation, parsing,
616 /// or seeded deserialization fails.
617 pub fn decode_seed_utf8<'de, S>(
618 &mut self,
619 seed: S,
620 input: &'de [u8],
621 ) -> Result<S::Value, JsonDecodeError<R, Q>>
622 where
623 S: DeserializeSeed<'de>,
624 {
625 self.engine
626 .decode_seed_utf8(seed, input, self.diagnostic_policy)
627 }
628
629 /// Decodes a unique-key JSON document into an owned target.
630 ///
631 /// The document is first materialized under the strict number contract,
632 /// then exposed as native Serde events even with `arbitrary_precision`.
633 /// Source construction uses the configured value depth budget and has no
634 /// separate fixed container limit. Targets cannot borrow the input, and
635 /// RawValue targets receive reconstructed JSON.
636 ///
637 /// # Type Parameters
638 ///
639 /// * `T` - Owned target type deserialized from the unique-key document.
640 ///
641 /// # Parameters
642 ///
643 /// * `input` - Complete JSON text to decode.
644 ///
645 /// # Returns
646 ///
647 /// The decoded owned value after unique-key validation succeeds.
648 ///
649 /// # Errors
650 ///
651 /// Returns an input, syntax, budget, duplicate-key, construction-depth,
652 /// or target-deserialization error. Value usage commits only on success.
653 pub fn decode_unique_str<T>(&mut self, input: &str) -> Result<T, JsonDecodeError<R, Q>>
654 where
655 T: DeserializeOwned,
656 {
657 self.decode_unique_utf8(input.as_bytes())
658 }
659
660 /// Decodes a unique-key UTF-8 JSON document into an owned target.
661 ///
662 /// See [`Self::decode_unique_str`] for numeric and materialization rules.
663 ///
664 /// # Type Parameters
665 ///
666 /// * `T` - Owned target type deserialized from the unique-key document.
667 ///
668 /// # Parameters
669 ///
670 /// * `input` - Complete UTF-8 JSON bytes to decode.
671 ///
672 /// # Returns
673 ///
674 /// The decoded owned value after unique-key validation succeeds.
675 ///
676 /// # Errors
677 ///
678 /// Returns an input, UTF-8, syntax, budget, materialization, or target
679 /// error.
680 pub fn decode_unique_utf8<T>(&mut self, input: &[u8]) -> Result<T, JsonDecodeError<R, Q>>
681 where
682 T: DeserializeOwned,
683 {
684 self.decode_unique_seed_utf8(TypedSeed::new(), input)
685 }
686
687 /// Decodes unique-key JSON through a seed producing an owned result.
688 ///
689 /// The seed receives native scalar, sequence, and map events from an
690 /// intermediate strict JSON tree. Input and value budgets cover the source
691 /// document. The temporary tree and target can coexist during decoding;
692 /// these lexical budgets are not a precise heap-memory bound.
693 /// Object iteration follows `serde_json::Map` ordering. The target's own
694 /// Serde semantics still apply: use `DuplicateKeyRejectingJsonValue`
695 /// instead of a bare `serde_json::Value` to preserve literal private keys.
696 ///
697 /// # Type Parameters
698 ///
699 /// * `S` - Seed that controls construction of the owned result.
700 /// * `T` - Owned result type produced by `S`.
701 ///
702 /// # Parameters
703 ///
704 /// * `seed` - Serde seed used to deserialize the materialized document.
705 /// * `input` - Complete UTF-8 JSON bytes to decode.
706 ///
707 /// # Returns
708 ///
709 /// The owned value produced by `seed` after unique-key validation.
710 ///
711 /// # Errors
712 ///
713 /// Returns a structured decode error for input admission, invalid syntax,
714 /// duplicate keys, configured value-depth failure, or seed failure.
715 /// Materialization errors retain source coordinates; target errors have
716 /// no original source position and are redacted by default.
717 pub fn decode_unique_seed_utf8<S, T>(
718 &mut self,
719 seed: S,
720 input: &[u8],
721 ) -> Result<T, JsonDecodeError<R, Q>>
722 where
723 S: for<'de> DeserializeSeed<'de, Value = T>,
724 {
725 self.engine
726 .decode_unique_seed_utf8(seed, input, self.diagnostic_policy)
727 }
728
729 /// Decodes a complete JSON string while requiring a top-level object.
730 ///
731 /// The top-level check is performed before the decoded value is committed,
732 /// so an array, scalar, or otherwise valid non-object document is rejected.
733 ///
734 /// # Type Parameters
735 ///
736 /// * `T` - Target type deserialized from the object document.
737 ///
738 /// # Parameters
739 ///
740 /// * `input` - Complete JSON text, which the returned value may borrow.
741 ///
742 /// # Returns
743 ///
744 /// The deserialized object value on success.
745 ///
746 /// # Errors
747 ///
748 /// Returns a structured error for accounting, parsing, top-level-kind, or
749 /// deserialization failures.
750 pub fn decode_object_str<'de, T>(&mut self, input: &'de str) -> Result<T, JsonDecodeError<R, Q>>
751 where
752 T: Deserialize<'de>,
753 {
754 self.decode_object_utf8(input.as_bytes())
755 }
756
757 /// Decodes a complete UTF-8 byte slice while requiring a top-level object.
758 ///
759 /// A syntactically valid array or scalar is rejected by the top-level
760 /// constraint before the decoded value is committed.
761 ///
762 /// # Type Parameters
763 ///
764 /// * `T` - Target type deserialized from the object document.
765 ///
766 /// # Parameters
767 ///
768 /// * `input` - Complete UTF-8 JSON bytes, which the returned value may
769 /// borrow.
770 ///
771 /// # Returns
772 ///
773 /// The deserialized object value on success.
774 ///
775 /// # Errors
776 ///
777 /// Returns a structured error for accounting, UTF-8 validation, parsing,
778 /// top-level-kind, or deserialization failures.
779 pub fn decode_object_utf8<'de, T>(
780 &mut self,
781 input: &'de [u8],
782 ) -> Result<T, JsonDecodeError<R, Q>>
783 where
784 T: Deserialize<'de>,
785 {
786 self.engine.decode_seed_utf8_with_top_level(
787 TypedSeed::new(),
788 input,
789 self.diagnostic_policy,
790 Some(JsonRootKind::Object),
791 )
792 }
793
794 /// Decodes a complete JSON string while requiring a top-level array.
795 ///
796 /// # Type Parameters
797 ///
798 /// * `T` - Element type deserialized from the array.
799 ///
800 /// # Parameters
801 ///
802 /// * `input` - Complete JSON text, which the returned elements may borrow.
803 ///
804 /// # Returns
805 ///
806 /// The decoded array elements on success.
807 ///
808 /// # Errors
809 ///
810 /// Returns a structured error for accounting, parsing, top-level-kind, or
811 /// deserialization failures.
812 pub fn decode_array_str<'de, T>(
813 &mut self,
814 input: &'de str,
815 ) -> Result<Vec<T>, JsonDecodeError<R, Q>>
816 where
817 T: Deserialize<'de>,
818 {
819 self.decode_array_utf8(input.as_bytes())
820 }
821
822 /// Decodes a complete UTF-8 byte slice while requiring a top-level array.
823 ///
824 /// # Type Parameters
825 ///
826 /// * `T` - Element type deserialized from the array.
827 ///
828 /// # Parameters
829 ///
830 /// * `input` - Complete UTF-8 JSON bytes, which the returned elements may
831 /// borrow.
832 ///
833 /// # Returns
834 ///
835 /// The decoded array elements on success.
836 ///
837 /// # Errors
838 ///
839 /// Returns a structured error for accounting, UTF-8 validation, parsing,
840 /// top-level-kind, or deserialization failures.
841 pub fn decode_array_utf8<'de, T>(
842 &mut self,
843 input: &'de [u8],
844 ) -> Result<Vec<T>, JsonDecodeError<R, Q>>
845 where
846 T: Deserialize<'de>,
847 {
848 self.engine.decode_seed_utf8_with_top_level(
849 TypedSeed::new(),
850 input,
851 self.diagnostic_policy,
852 Some(JsonRootKind::Array),
853 )
854 }
855
856 /// Validates and accounts for one complete JSON string without
857 /// materializing a target value.
858 ///
859 /// # Parameters
860 ///
861 /// * `input` - Complete JSON text to validate and account for.
862 ///
863 /// # Returns
864 ///
865 /// `Ok(())` after the complete document is valid and accounted for.
866 ///
867 /// # Errors
868 ///
869 /// Returns a structured error when accounting or JSON parsing fails. No
870 /// target value is allocated; `str` input is already valid UTF-8.
871 pub fn validate_str(&mut self, input: &str) -> Result<(), JsonDecodeError<R, Q>> {
872 self.validate_utf8(input.as_bytes())
873 }
874
875 /// Validates and accounts for one complete UTF-8 JSON byte slice without
876 /// materializing a target value.
877 ///
878 /// # Parameters
879 ///
880 /// * `input` - Complete UTF-8 JSON bytes to validate and account for.
881 ///
882 /// # Returns
883 ///
884 /// `Ok(())` after the complete document is valid and accounted for.
885 ///
886 /// # Errors
887 ///
888 /// Returns a structured error when accounting, UTF-8 validation, or JSON
889 /// parsing fails. No target value is allocated.
890 pub fn validate_utf8(&mut self, input: &[u8]) -> Result<(), JsonDecodeError<R, Q>> {
891 self.engine.validate_utf8(input, self.diagnostic_policy)
892 }
893}