Skip to main content

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}