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}