Skip to main content

qubit_value/value_wire/
value_wire_ref_v1.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//! Borrowed V1 envelope serialization.
10
11#[cfg(feature = "json")]
12use std::io::Write;
13
14#[cfg(feature = "json")]
15use qubit_budget::json::JsonEncodeLimits;
16#[cfg(feature = "json")]
17use qubit_budget::json::JsonEncodeSession;
18#[cfg(feature = "json")]
19use qubit_json::encode::JsonEncoder;
20use serde::Serialize;
21use serde::Serializer;
22
23use super::ValueWireEncodeError;
24use super::ValueWirePayloadRefV1;
25use super::serialize_wire;
26use crate::MultiValues;
27use crate::Value;
28use crate::ValueContainer;
29
30/// Borrowed standalone V1 envelope for serialization without cloning.
31///
32/// # Type Parameters
33///
34/// * `'a` - Lifetime of the runtime payload borrowed for serialization.
35///
36/// # Examples
37///
38/// ```
39/// use qubit_value::{Value, ValueWireRefV1};
40///
41/// let value = Value::from(42_i32);
42/// let _wire = ValueWireRefV1::from_value(&value).unwrap();
43/// ```
44#[must_use]
45pub struct ValueWireRefV1<'a> {
46    /// Borrowed V1 payload carried by this versioned envelope.
47    value: ValueWirePayloadRefV1<'a>,
48}
49
50impl<'a> ValueWireRefV1<'a> {
51    /// Borrows a scalar after validating V1's finite-float invariant.
52    ///
53    /// # Parameters
54    ///
55    /// * `value` - Scalar runtime value to validate and borrow.
56    ///
57    /// # Returns
58    ///
59    /// A standalone borrowed V1 envelope containing the scalar.
60    ///
61    /// # Errors
62    ///
63    /// Returns [`ValueWireEncodeError`] when the scalar violates V1 numeric
64    /// representation constraints.
65    #[inline(always)]
66    pub fn from_value(value: &'a Value) -> Result<Self, ValueWireEncodeError> {
67        ValueWirePayloadRefV1::from_value(value).map(Self::new)
68    }
69    /// Borrows a collection after validating V1's finite-float invariant.
70    ///
71    /// # Parameters
72    ///
73    /// * `values` - Homogeneous runtime collection to validate and borrow.
74    ///
75    /// # Returns
76    ///
77    /// A standalone borrowed V1 envelope containing the collection.
78    ///
79    /// # Errors
80    ///
81    /// Returns [`ValueWireEncodeError`] when an element violates V1 numeric
82    /// representation constraints.
83    #[inline(always)]
84    pub fn from_values(values: &'a MultiValues) -> Result<Self, ValueWireEncodeError> {
85        ValueWirePayloadRefV1::from_values(values).map(Self::new)
86    }
87    /// Borrows an explicit shape after validating V1's finite-float invariant.
88    ///
89    /// # Parameters
90    ///
91    /// * `value` - Explicit scalar-or-collection value to validate and borrow.
92    ///
93    /// # Returns
94    ///
95    /// A standalone borrowed V1 envelope preserving the original shape.
96    ///
97    /// # Errors
98    ///
99    /// Returns [`ValueWireEncodeError`] when any contained value violates V1
100    /// numeric representation constraints.
101    #[inline(always)]
102    pub fn from_container(value: &'a ValueContainer) -> Result<Self, ValueWireEncodeError> {
103        ValueWirePayloadRefV1::from_container(value).map(Self::new)
104    }
105    /// Wraps an already validated borrowed payload.
106    ///
107    /// # Parameters
108    ///
109    /// * `value` - Validated borrowed payload to place in the V1 envelope.
110    ///
111    /// # Returns
112    ///
113    /// A standalone borrowed V1 envelope.
114    #[inline(always)]
115    pub const fn new(value: ValueWirePayloadRefV1<'a>) -> Self {
116        Self { value }
117    }
118
119    /// Encodes the borrowed V1 envelope into a compact JSON vector.
120    ///
121    /// # Returns
122    ///
123    /// Compact UTF-8 JSON bytes for the complete V1 envelope.
124    ///
125    /// # Errors
126    ///
127    /// Returns [`ValueWireEncodeError`] for resource or serialization failures.
128    #[cfg(feature = "json")]
129    #[inline(always)]
130    pub fn to_json_vec(&self) -> Result<Vec<u8>, ValueWireEncodeError> {
131        self.to_json_vec_with_limits(super::default_json_encode_limits())
132    }
133
134    /// Encodes the borrowed V1 envelope with explicit JSON resource limits.
135    ///
136    /// # Parameters
137    ///
138    /// * `limits` - Resource limits enforced during JSON encoding.
139    ///
140    /// # Returns
141    ///
142    /// Compact UTF-8 JSON bytes for the complete V1 envelope.
143    ///
144    /// # Errors
145    ///
146    /// Returns [`ValueWireEncodeError`] when encoding exceeds `limits` or
147    /// Serde rejects the envelope.
148    #[cfg(feature = "json")]
149    #[inline]
150    pub fn to_json_vec_with_limits(&self, limits: JsonEncodeLimits) -> Result<Vec<u8>, ValueWireEncodeError> {
151        let session = JsonEncodeSession::from_limits(limits);
152        JsonEncoder::new(session)
153            .to_vec(self)
154            .map_err(ValueWireEncodeError::from)
155    }
156
157    /// Encodes the borrowed V1 envelope to a writer with default limits.
158    ///
159    /// # Type Parameters
160    ///
161    /// * `W` - Destination writer type.
162    ///
163    /// # Parameters
164    ///
165    /// * `writer` - Destination receiving the complete V1 JSON envelope.
166    ///
167    /// # Returns
168    ///
169    /// `Ok(())` after the complete envelope is written.
170    ///
171    /// # Errors
172    ///
173    /// Returns [`ValueWireEncodeError`] for resource, serialization, or writer
174    /// failures.
175    #[cfg(feature = "json")]
176    #[inline(always)]
177    pub fn to_json_writer<W>(&self, writer: W) -> Result<(), ValueWireEncodeError>
178    where
179        W: Write,
180    {
181        self.to_json_writer_with_limits(writer, super::default_json_encode_limits())
182    }
183
184    /// Encodes the borrowed V1 envelope to a writer with explicit limits.
185    ///
186    /// # Type Parameters
187    ///
188    /// * `W` - Destination writer type.
189    ///
190    /// # Parameters
191    ///
192    /// * `writer` - Destination receiving the complete V1 JSON envelope.
193    /// * `limits` - Resource limits enforced during JSON encoding.
194    ///
195    /// # Returns
196    ///
197    /// `Ok(())` after the complete envelope is written.
198    ///
199    /// # Errors
200    ///
201    /// Returns [`ValueWireEncodeError`] when encoding exceeds `limits`, Serde
202    /// rejects the envelope, or `writer` rejects output.
203    #[cfg(feature = "json")]
204    #[inline]
205    pub fn to_json_writer_with_limits<W>(&self, writer: W, limits: JsonEncodeLimits) -> Result<(), ValueWireEncodeError>
206    where
207        W: Write,
208    {
209        let session = JsonEncodeSession::from_limits(limits);
210        JsonEncoder::new(session)
211            .write_buffered(writer, self)
212            .map_err(ValueWireEncodeError::from)
213    }
214}
215
216impl<'a> TryFrom<&'a Value> for ValueWireRefV1<'a> {
217    type Error = ValueWireEncodeError;
218    /// Borrows and validates a scalar.
219    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
220        Self::from_value(value)
221    }
222}
223
224impl<'a> TryFrom<&'a MultiValues> for ValueWireRefV1<'a> {
225    type Error = ValueWireEncodeError;
226    /// Borrows and validates a collection.
227    fn try_from(values: &'a MultiValues) -> Result<Self, Self::Error> {
228        Self::from_values(values)
229    }
230}
231
232impl<'a> TryFrom<&'a ValueContainer> for ValueWireRefV1<'a> {
233    type Error = ValueWireEncodeError;
234    /// Borrows and validates an explicit shape.
235    fn try_from(value: &'a ValueContainer) -> Result<Self, Self::Error> {
236        Self::from_container(value)
237    }
238}
239
240impl Serialize for ValueWireRefV1<'_> {
241    /// Serializes the borrowed runtime shape through the V1 envelope.
242    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
243    where
244        S: Serializer,
245    {
246        serialize_wire(self.value.shape(), serializer)
247    }
248}