qubit_value/value_wire/value_wire_v1_seed.rs
1// =============================================================================
2// Copyright (c) 2025 - 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8
9//! Explicit Serde seed for decoding one V1 envelope.
10
11use serde::Deserializer;
12use serde::de::DeserializeSeed;
13
14use super::ValueWirePayloadV1;
15use super::ValueWireV1;
16use super::deserialize_wire;
17
18/// Explicit Serde seed for decoding one V1 envelope.
19///
20/// Use this seed with a decoder that enforces the resource limits appropriate
21/// for the surrounding document. For complete JSON input, prefer the bounded
22/// JSON decode helpers on `ValueWireV1`.
23///
24/// Errors from decoding the envelope use a fixed diagnostic so malformed
25/// field names and values from untrusted input are not disclosed. Bounded
26/// helpers provide richer safe metadata through `InvalidJson`. Resource
27/// limits do not sanitize diagnostics, and reader or writer I/O sources may
28/// contain application-defined details that require the application's logging
29/// policy.
30///
31/// # Examples
32///
33/// With the `json` feature, a complete envelope can be decoded through the
34/// public `JsonDecoder` entry point:
35///
36/// ```rust
37/// # #[cfg(feature = "json")]
38/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
39/// use qubit_budget::json::{JsonDecodeLimits, JsonDecodeSession};
40/// use qubit_json::decode::JsonDecoder;
41/// use qubit_value::ValueWireV1Seed;
42///
43/// let limits = JsonDecodeLimits::builder().max_input_bytes(256usize).build();
44/// let session = JsonDecodeSession::from_limits(limits);
45/// let mut decoder = JsonDecoder::new(session);
46/// let value = decoder.decode_unique_seed_utf8(
47/// ValueWireV1Seed::new(),
48/// br#"{"version":1,"value":{"scalar":{"int32":7}}}"#,
49/// )?;
50/// assert_eq!(value.into_container().data_type(), qubit_datatype::DataType::Int32);
51/// # Ok(())
52/// # }
53/// # #[cfg(not(feature = "json"))]
54/// # fn main() {}
55/// ```
56#[derive(Debug, Clone, Copy, Default)]
57pub struct ValueWireV1Seed;
58
59impl ValueWireV1Seed {
60 /// Creates a seed for one V1 envelope.
61 ///
62 /// # Returns
63 ///
64 /// A stateless seed to pass to a resource-bounded deserializer.
65 #[must_use = "the seed should be passed to a bounded deserializer"]
66 #[inline(always)]
67 pub const fn new() -> Self {
68 Self
69 }
70}
71
72impl<'de> DeserializeSeed<'de> for ValueWireV1Seed {
73 /// Validated V1 envelope produced by decoding the input.
74 type Value = ValueWireV1;
75
76 /// Deserializes one validated V1 runtime container into the DTO.
77 ///
78 /// # Type Parameters
79 ///
80 /// * `D` - Serde deserializer supplying the V1 envelope, with input borrows
81 /// valid for `'de`.
82 ///
83 /// # Parameters
84 ///
85 /// * `self` - Stateless seed consumed by the decoding operation.
86 /// * `deserializer` - Source of the envelope; the caller is responsible for
87 /// enforcing appropriate resource limits.
88 ///
89 /// # Returns
90 ///
91 /// The decoded and version-validated V1 envelope.
92 ///
93 /// # Errors
94 ///
95 /// Returns `D::Error` if decoding fails or the envelope declares an
96 /// unsupported version. Malformed envelope diagnostics do not include
97 /// input-derived field names or values.
98 #[inline(always)]
99 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
100 where
101 D: Deserializer<'de>,
102 {
103 deserialize_wire(deserializer)
104 .map(ValueWirePayloadV1::from_decoded)
105 .map(ValueWireV1::new)
106 }
107}