qubit_value/
value_error.rs1#[cfg(all(feature = "converter", feature = "json"))]
13use qubit_budget::MeasuredBudgetError;
14#[cfg(all(feature = "converter", feature = "json"))]
15use qubit_datatype::ConversionResource;
16#[cfg(feature = "converter")]
17use qubit_datatype::DataConversionError;
18#[cfg(feature = "converter")]
19use qubit_datatype::DataConversionErrorKind;
20#[cfg(feature = "converter")]
21use qubit_datatype::DataListConversionError;
22use qubit_datatype::DataType;
23use thiserror::Error;
24
25use crate::ValueMissing;
26
27#[non_exhaustive]
51#[must_use]
52#[derive(Debug, Clone, Error)]
53pub enum ValueError {
54 #[cfg(all(feature = "converter", feature = "json"))]
56 #[error("JSON projection limit for {data_type} at collection index {source_index:?}: {source}")]
57 JsonProjectionLimit {
58 data_type: DataType,
60 source_index: Option<usize>,
62 #[source]
64 source: MeasuredBudgetError<ConversionResource, u64>,
65 },
66
67 #[error("Missing value: {0}")]
69 Missing(
70 #[source]
72 ValueMissing,
73 ),
74
75 #[error("Type mismatch: expected {expected}, actual {actual}")]
77 TypeMismatch {
78 expected: DataType,
80 actual: DataType,
82 },
83
84 #[cfg(feature = "converter")]
86 #[error("Conversion error: {0}")]
87 Conversion(
88 #[source]
90 DataConversionError,
91 ),
92
93 #[cfg(feature = "converter")]
95 #[error("List conversion error: {0}")]
96 ListConversion(
97 #[source]
99 DataListConversionError,
100 ),
101}
102
103impl PartialEq for ValueError {
104 fn eq(&self, other: &Self) -> bool {
106 match (self, other) {
107 (Self::Missing(left), Self::Missing(right)) => left == right,
108 (
109 Self::TypeMismatch {
110 expected: le,
111 actual: la,
112 },
113 Self::TypeMismatch {
114 expected: re,
115 actual: ra,
116 },
117 ) => le == re && la == ra,
118 #[cfg(feature = "converter")]
119 (Self::Conversion(left), Self::Conversion(right)) => left == right,
120 #[cfg(feature = "converter")]
121 (Self::ListConversion(left), Self::ListConversion(right)) => left == right,
122 #[cfg(all(feature = "converter", feature = "json"))]
123 (
124 Self::JsonProjectionLimit {
125 data_type: lt,
126 source_index: li,
127 source: ls,
128 },
129 Self::JsonProjectionLimit {
130 data_type: rt,
131 source_index: ri,
132 source: rs,
133 },
134 ) => {
135 lt == rt
136 && li == ri
137 && ls.resource() == rs.resource()
138 && ls.budget_error() == rs.budget_error()
139 && ls.quantity_error() == rs.quantity_error()
140 }
141 _ => false,
142 }
143 }
144}
145
146impl Eq for ValueError {}
147
148impl ValueError {
149 #[must_use]
155 #[inline(always)]
156 pub const fn is_missing(&self) -> bool {
157 matches!(self, Self::Missing(_))
158 }
159
160 #[must_use]
166 #[inline(always)]
167 pub const fn missing(&self) -> Option<&ValueMissing> {
168 match self {
169 Self::Missing(missing) => Some(missing),
170 Self::TypeMismatch { .. } => None,
171 #[cfg(all(feature = "converter", feature = "json"))]
172 Self::JsonProjectionLimit { .. } => None,
173 #[cfg(feature = "converter")]
174 Self::Conversion(_) | Self::ListConversion(_) => None,
175 }
176 }
177}
178
179#[cfg(feature = "converter")]
180impl From<DataConversionError> for ValueError {
181 fn from(error: DataConversionError) -> Self {
182 if error.is_missing() || error.kind() == DataConversionErrorKind::EmptyCollection {
183 return Self::Missing(ValueMissing::from_conversion(error, None));
184 }
185 Self::Conversion(error)
186 }
187}
188
189#[cfg(feature = "converter")]
190impl From<DataListConversionError> for ValueError {
191 fn from(error: DataListConversionError) -> Self {
192 let (source_index, source) = error.into_parts();
193 if source.is_missing() || source.kind() == DataConversionErrorKind::EmptyCollection {
194 return Self::Missing(ValueMissing::from_conversion(source, Some(source_index)));
195 }
196 Self::ListConversion(DataListConversionError::new(source_index, source))
197 }
198}
199
200pub type ValueResult<T> = Result<T, ValueError>;