qubit-value 0.13.0

Type-safe containers for single, multi-valued, and named runtime values
Documentation
// =============================================================================
//    Copyright (c) 2025 - 2026 Haixing Hu.
//
//    SPDX-License-Identifier: Apache-2.0
//
//    Licensed under the Apache License, Version 2.0.
// =============================================================================

//! Explicit Serde seed for decoding one V1 envelope.

use serde::Deserializer;
use serde::de::DeserializeSeed;

use super::ValueWirePayloadV1;
use super::ValueWireV1;
use super::deserialize_wire;

/// Explicit Serde seed for decoding one V1 envelope.
///
/// Use this seed with a decoder that enforces the resource limits appropriate
/// for the surrounding document. For complete JSON input, prefer the bounded
/// JSON decode helpers on `ValueWireV1`.
///
/// This generic Serde seed preserves the surrounding deserializer's error
/// semantics; its diagnostics may contain input-derived text. Bounded helpers
/// map target-deserialization failures to `InvalidJson` metadata containing
/// only the Serde category and location. Resource limits do not sanitize
/// diagnostics, and reader or writer I/O sources may contain
/// application-defined details that require the application's logging policy.
///
/// # Examples
///
/// With the `json` feature, a complete envelope can be decoded through the
/// public `JsonDecoder` entry point:
///
/// ```rust
/// # #[cfg(feature = "json")]
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use qubit_budget::json::{JsonDecodeLimits, JsonDecodeSession};
/// use qubit_json::decode::JsonDecoder;
/// use qubit_value::ValueWireV1Seed;
///
/// let limits = JsonDecodeLimits::builder().max_input_bytes(256usize).build();
/// let session = JsonDecodeSession::from_limits(limits);
/// let mut decoder = JsonDecoder::new(session);
/// let value = decoder.decode_unique_seed_utf8(
///     ValueWireV1Seed::new(),
///     br#"{"version":1,"value":{"scalar":{"int32":7}}}"#,
/// )?;
/// assert_eq!(value.into_container().data_type(), qubit_datatype::DataType::Int32);
/// # Ok(())
/// # }
/// # #[cfg(not(feature = "json"))]
/// # fn main() {}
/// ```
#[derive(Debug, Clone, Copy, Default)]
pub struct ValueWireV1Seed;

impl ValueWireV1Seed {
    /// Creates a seed for one V1 envelope.
    ///
    /// # Returns
    ///
    /// A stateless seed to pass to a resource-bounded deserializer.
    #[must_use = "the seed should be passed to a bounded deserializer"]
    #[inline(always)]
    pub const fn new() -> Self {
        Self
    }
}

impl<'de> DeserializeSeed<'de> for ValueWireV1Seed {
    /// Validated V1 envelope produced by decoding the input.
    type Value = ValueWireV1;

    /// Deserializes one validated V1 runtime container into the DTO.
    ///
    /// # Type Parameters
    ///
    /// * `D` - Serde deserializer supplying the V1 envelope, with input borrows
    ///   valid for `'de`.
    ///
    /// # Parameters
    ///
    /// * `self` - Stateless seed consumed by the decoding operation.
    /// * `deserializer` - Source of the envelope; the caller is responsible for
    ///   enforcing appropriate resource limits.
    ///
    /// # Returns
    ///
    /// The decoded and version-validated V1 envelope.
    ///
    /// # Errors
    ///
    /// Returns `D::Error` if decoding fails or the envelope declares an
    /// unsupported version. Diagnostics retain the deserializer's error
    /// semantics and may contain input-derived text.
    #[inline(always)]
    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserialize_wire(deserializer)
            .map(ValueWirePayloadV1::from_decoded)
            .map(ValueWireV1::new)
    }
}