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