Skip to main content

qubit_value/value/
value_getter.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//! `TryFrom<&Value>` implementations for strict typed reads.
10
11use qubit_datatype::DataType;
12
13use super::ValueRepr;
14use super::value::Value;
15use crate::ValueMissing;
16use crate::value_error::ValueError;
17use crate::value_error::ValueResult;
18
19/// Implements strict borrowed scalar reads from the shared value table.
20macro_rules! impl_value_try_from_table {
21    (
22        ;
23        $(
24            (
25                [$($cfg:meta),*],
26                $variant:ident,
27                $type:ty,
28                $data_type:expr,
29                $materialization:ident,
30                $json_class:ident,
31                $number_projection:ident,
32                $value_doc:literal,
33                $multi_doc:literal
34                $(, $_wire:tt)*
35            )
36        ),+ $(,)?
37    ) => {
38        $(
39            $(#[$cfg])*
40            impl TryFrom<&Value> for $type {
41                type Error = ValueError;
42
43                #[inline(always)]
44                fn try_from(value: &Value) -> ValueResult<$type> {
45                    match &value.repr {
46                        ValueRepr::$variant(value) => {
47                            Ok(materialize_value_storage!($variant, $materialization, value))
48                        }
49                        ValueRepr::Unset(actual) if *actual == $data_type => {
50                            Err(ValueError::Missing(ValueMissing::unset_scalar(*actual, *actual)))
51                        }
52                        _ => Err(ValueError::TypeMismatch {
53                            expected: $data_type,
54                            actual: value.data_type(),
55                        }),
56                    }
57                }
58            }
59        )+
60    };
61}
62
63for_each_value_type!(impl_value_try_from_table);
64
65/// Implements zero-copy scalar reads from the shared value table.
66macro_rules! impl_value_borrowed_try_from_table {
67    (
68        ;
69        $(
70            (
71                [$($cfg:meta),*],
72                $variant:ident,
73                $type:ty,
74                $data_type:expr,
75                $materialization:ident,
76                $json_class:ident,
77                $number_projection:ident,
78                $value_doc:literal,
79                $multi_doc:literal
80                $(, $_wire:tt)*
81            )
82        ),+ $(,)?
83    ) => {
84        $(
85            $(#[$cfg])*
86            impl<'a> TryFrom<&'a Value> for &'a $type {
87                type Error = ValueError;
88
89                #[inline(always)]
90                fn try_from(value: &'a Value) -> ValueResult<Self> {
91                    match &value.repr {
92                        ValueRepr::$variant(value) => Ok(value_storage_ref!($variant, value)),
93                        ValueRepr::Unset(actual) if *actual == $data_type => {
94                            Err(ValueError::Missing(ValueMissing::unset_scalar(*actual, *actual)))
95                        }
96                        _ => Err(ValueError::TypeMismatch {
97                            expected: $data_type,
98                            actual: value.data_type(),
99                        }),
100                    }
101                }
102            }
103
104            $(#[$cfg])*
105            impl TryFrom<Value> for $type {
106                type Error = ValueError;
107
108                #[inline(always)]
109                fn try_from(value: Value) -> ValueResult<Self> {
110                    match value.repr {
111                        ValueRepr::$variant(value) => Ok(move_value_storage!($variant, value)),
112                        ValueRepr::Unset(actual) if actual == $data_type => {
113                            Err(ValueError::Missing(ValueMissing::unset_scalar(actual, actual)))
114                        }
115                        other => Err(ValueError::TypeMismatch {
116                            expected: $data_type,
117                            actual: Value { repr: other }.data_type(),
118                        }),
119                    }
120                }
121            }
122        )+
123    };
124}
125
126for_each_value_type!(impl_value_borrowed_try_from_table);
127
128impl<'a> TryFrom<&'a Value> for &'a str {
129    type Error = ValueError;
130
131    #[inline(always)]
132    fn try_from(value: &'a Value) -> ValueResult<Self> {
133        match &value.repr {
134            ValueRepr::String(value) => Ok(value.as_str()),
135            ValueRepr::Unset(actual) if *actual == DataType::String => {
136                Err(ValueError::Missing(ValueMissing::unset_scalar(*actual, *actual)))
137            }
138            _ => Err(ValueError::TypeMismatch {
139                expected: DataType::String,
140                actual: value.data_type(),
141            }),
142        }
143    }
144}