Skip to main content

qubit_value/value_wire/
value_wire_payload_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 unversioned V1 payload.
10
11use serde::Deserialize;
12use serde::Deserializer;
13use serde::de::DeserializeSeed;
14
15use super::ValueWirePayloadV1;
16use super::WireShapeOwned;
17
18/// Explicit Serde seed for decoding one unversioned V1 payload.
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
22/// bounded JSON decode helpers on `ValueWirePayloadV1`.
23///
24/// This generic Serde seed preserves the surrounding deserializer's error
25/// semantics; its diagnostics may contain input-derived text. Bounded helpers
26/// map target-deserialization failures to `InvalidJson` metadata containing
27/// only the Serde category and location. Resource limits do not sanitize
28/// diagnostics, and reader or writer I/O sources may contain
29/// application-defined details that require the application's logging policy.
30///
31/// # Examples
32///
33/// With the `json` feature, use it when the surrounding protocol owns the
34/// version envelope and its decoder session:
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::ValueWirePayloadV1Seed;
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 payload = decoder.decode_unique_seed_utf8(
47///     ValueWirePayloadV1Seed::new(),
48///     br#"{"scalar":{"int32":7}}"#,
49/// )?;
50/// assert_eq!(payload.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 ValueWirePayloadV1Seed;
58
59impl ValueWirePayloadV1Seed {
60    /// Creates a seed for one unversioned V1 payload.
61    ///
62    /// # Returns
63    ///
64    /// A stateless seed to pass to the surrounding protocol's 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 ValueWirePayloadV1Seed {
73    /// Owned scalar-or-collection payload decoded without a version envelope.
74    type Value = ValueWirePayloadV1;
75
76    /// Deserializes one unversioned V1 shape.
77    ///
78    /// # Type Parameters
79    ///
80    /// * `D` - Serde deserializer whose input is valid for `'de` and whose
81    ///   resource limits are controlled by the surrounding protocol.
82    ///
83    /// # Parameters
84    ///
85    /// * `self` - Stateless seed consumed by this decoding operation.
86    /// * `deserializer` - Decoder positioned at one unversioned V1 payload.
87    ///
88    /// # Returns
89    ///
90    /// An owned payload preserving the decoded scalar or collection shape.
91    ///
92    /// # Errors
93    ///
94    /// Propagates `D::Error` when the input cannot be decoded as a V1 shape,
95    /// preserving the deserializer's diagnostics, which may contain input text.
96    #[inline(always)]
97    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
98    where
99        D: Deserializer<'de>,
100    {
101        Ok(ValueWirePayloadV1::from_decoded(
102            WireShapeOwned::deserialize(deserializer)?.into(),
103        ))
104    }
105}