qubit_value/multi_values/
multi_values_identity.rs1use std::hash::Hash;
11use std::hash::Hasher;
12
13#[cfg(feature = "json")]
14use qubit_budget::MeasuredBudgetError;
15#[cfg(feature = "json")]
16use qubit_budget::ResourceQuantity;
17#[cfg(feature = "json")]
18use qubit_budget::json::JsonValueBudget;
19
20use super::MultiValuesRepr;
21use super::multi_values::MultiValues;
22use crate::identity::canonical_f32_bits;
23use crate::identity::canonical_f64_bits;
24#[cfg(feature = "big-decimal")]
25use crate::identity::hash_big_decimal;
26#[cfg(feature = "json")]
27use crate::identity::hash_json;
28use crate::identity::hash_string_map;
29#[cfg(feature = "json")]
30use crate::identity::json_eq;
31
32macro_rules! payloads_eq {
34 (Float32, $left:expr, $right:expr) => {
35 $left.len() == $right.len()
36 && $left
37 .iter()
38 .zip($right)
39 .all(|(left, right)| canonical_f32_bits(*left) == canonical_f32_bits(*right))
40 };
41 (Float64, $left:expr, $right:expr) => {
42 $left.len() == $right.len()
43 && $left
44 .iter()
45 .zip($right)
46 .all(|(left, right)| canonical_f64_bits(*left) == canonical_f64_bits(*right))
47 };
48 (Json, $left:expr, $right:expr) => {
49 $left.len() == $right.len() && $left.iter().zip($right).all(|(left, right)| json_eq(left, right))
50 };
51 ($variant:ident, $left:expr, $right:expr) => {
52 $left == $right
53 };
54}
55
56macro_rules! hash_payloads {
58 (Float32, $values:expr, $state:expr) => {{
59 $values.len().hash($state);
60 for value in $values {
61 canonical_f32_bits(*value).hash($state);
62 }
63 }};
64 (Float64, $values:expr, $state:expr) => {{
65 $values.len().hash($state);
66 for value in $values {
67 canonical_f64_bits(*value).hash($state);
68 }
69 }};
70 (BigDecimal, $values:expr, $state:expr) => {{
71 $values.len().hash($state);
72 for value in $values {
73 hash_big_decimal(value, $state);
74 }
75 }};
76 (StringMap, $values:expr, $state:expr) => {{
77 $values.len().hash($state);
78 for value in $values {
79 hash_string_map(value, $state);
80 }
81 }};
82 (Json, $values:expr, $state:expr) => {{
83 $values.len().hash($state);
84 for value in $values {
85 hash_json(value, $state);
86 }
87 }};
88 ($variant:ident, $values:expr, $state:expr) => {
89 $values.hash($state)
90 };
91}
92
93#[cfg(feature = "json")]
95macro_rules! budgeted_hash_payload {
96 (Json, $value:expr, $state:expr) => {{
97 let _ = $value;
98 unreachable!("JSON payload hashing is handled by MultiValues::hash_with_json_budget")
99 }};
100 ($variant:ident, $value:expr, $state:expr) => {
101 hash_payloads!($variant, $value, $state)
102 };
103}
104
105#[cfg(feature = "json")]
107macro_rules! budgeted_payload_match {
108 ($repr:expr, $state:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
109 match $repr {
110 MultiValuesRepr::Unset(data_type) => data_type.hash($state),
111 $($(#[$cfg])* MultiValuesRepr::$variant(value) => {
112 budgeted_hash_payload!($variant, value, $state)
113 },)+
114 }
115 };
116}
117
118#[cfg(feature = "json")]
142pub(crate) fn hash_multi_values_payload_with_json_budget<H, R, Q>(
143 repr: &MultiValuesRepr,
144 state: &mut H,
145 _budget: &mut JsonValueBudget<R, Q>,
146) -> Result<(), MeasuredBudgetError<R, Q>>
147where
148 H: Hasher,
149 R: Clone,
150 Q: ResourceQuantity,
151{
152 for_each_value_type!(budgeted_payload_match, repr, state);
153 Ok(())
154}
155
156macro_rules! impl_multi_values_identity {
158 (
159 ;
160 $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?
161 ) => {
162 impl PartialEq for MultiValues {
163 fn eq(&self, other: &Self) -> bool {
164 match (&self.repr, &other.repr) {
165 (MultiValuesRepr::Unset(left), MultiValuesRepr::Unset(right)) => left == right,
166 $($(#[$cfg])*
167 (MultiValuesRepr::$variant(left), MultiValuesRepr::$variant(right)) => {
168 payloads_eq!($variant, left, right)
169 },)+
170 _ => false,
171 }
172 }
173 }
174
175 impl Eq for MultiValues {}
176
177 impl Hash for MultiValues {
178 fn hash<H: Hasher>(&self, state: &mut H) {
179 std::mem::discriminant(&self.repr).hash(state);
180 match &self.repr {
181 MultiValuesRepr::Unset(data_type) => data_type.hash(state),
182 $($(#[$cfg])*
183 MultiValuesRepr::$variant(values) => {
184 hash_payloads!($variant, values, state)
185 },)+
186 }
187 }
188 }
189 };
190}
191
192for_each_value_type!(impl_multi_values_identity);