Skip to main content

qubit_value/
strict_value_read.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//! Sealed public bound for strict reads from runtime value storage.
10use crate::MultiValues;
11use crate::Value;
12use crate::ValueError;
13use crate::ValueResult;
14
15mod internal;
16
17use self::internal::sealed::Sealed;
18
19/// Marks target types supported by exact, non-converting reads.
20///
21/// This trait is sealed because supported types are determined by the closed
22/// runtime [`qubit_datatype::DataType`] family. Domain conversions belong in
23/// explicit conversion boundaries, rather than changing strict-read semantics.
24///
25/// # Examples
26///
27/// ```
28/// use qubit_value::{StrictValueRead, Value, ValueResult};
29///
30/// fn read_exact<T: StrictValueRead>(value: &Value) -> ValueResult<T> {
31///     T::read_scalar(value)
32/// }
33///
34/// assert_eq!(read_exact::<i32>(&Value::from(42_i32)).unwrap(), 42);
35/// ```
36pub trait StrictValueRead: Sized + Sealed {
37    /// Strictly reads a scalar runtime value.
38    ///
39    /// # Parameters
40    ///
41    /// * `value` - Scalar runtime value to read without conversion.
42    ///
43    /// # Returns
44    ///
45    /// The exact stored scalar represented as `Self`.
46    ///
47    /// # Errors
48    ///
49    /// Returns [`ValueError::Missing`] for unset storage or
50    /// [`ValueError::TypeMismatch`] for a different runtime type.
51    #[doc(hidden)]
52    fn read_scalar(value: &Value) -> ValueResult<Self>;
53
54    /// Strictly reads the first item from a runtime collection.
55    ///
56    /// # Parameters
57    ///
58    /// * `values` - Runtime collection whose first item is read exactly.
59    ///
60    /// # Returns
61    ///
62    /// The first stored element represented as `Self`.
63    ///
64    /// # Errors
65    ///
66    /// Returns [`ValueError::Missing`] for unset or empty storage, or
67    /// [`ValueError::TypeMismatch`] for a different element type.
68    #[doc(hidden)]
69    fn read_collection_first(values: &MultiValues) -> ValueResult<Self>;
70
71    /// Strictly reads every item from a runtime collection.
72    ///
73    /// # Parameters
74    ///
75    /// * `values` - Runtime collection whose elements are cloned exactly.
76    ///
77    /// # Returns
78    ///
79    /// Every stored element in original order.
80    ///
81    /// # Errors
82    ///
83    /// Returns [`ValueError::Missing`] for unset storage or
84    /// [`ValueError::TypeMismatch`] for a different element type.
85    #[doc(hidden)]
86    fn read_collection_list(values: &MultiValues) -> ValueResult<Vec<Self>>;
87}
88
89impl<T> StrictValueRead for T
90where
91    for<'a> T: TryFrom<&'a Value, Error = ValueError> + TryFrom<&'a MultiValues, Error = ValueError>,
92    for<'a> Vec<T>: TryFrom<&'a MultiValues, Error = ValueError>,
93{
94    #[inline(always)]
95    fn read_scalar(value: &Value) -> ValueResult<Self> {
96        value.get()
97    }
98
99    #[inline(always)]
100    fn read_collection_first(values: &MultiValues) -> ValueResult<Self> {
101        values.get_first()
102    }
103
104    #[inline(always)]
105    fn read_collection_list(values: &MultiValues) -> ValueResult<Vec<Self>> {
106        values.get()
107    }
108}