qubit_value/multi_values/multi_values_core.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10
11//! Core generic accessors and state methods for `MultiValues`.
12
13use qubit_datatype::DataType;
14
15use crate::IntoValueDefault;
16use crate::value_error::{
17 ValueError,
18 ValueResult,
19};
20
21use super::multi_values::MultiValues;
22
23macro_rules! multi_values_data_type_match {
24 ($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
25 match $value {
26 MultiValues::Empty(dt) => *dt,
27 $(MultiValues::$variant(_) => $data_type,)+
28 }
29 };
30}
31
32macro_rules! multi_values_count_match {
33 ($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
34 match $value {
35 MultiValues::Empty(_) => 0,
36 $(MultiValues::$variant(values) => values.len(),)+
37 }
38 };
39}
40
41macro_rules! multi_values_clear_match {
42 ($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
43 match $value {
44 MultiValues::Empty(_) => {}
45 $(MultiValues::$variant(values) => values.clear(),)+
46 }
47 };
48}
49
50macro_rules! multi_values_append_match {
51 ($left:expr, $right:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
52 match ($left, $right) {
53 $(
54 (MultiValues::$variant(values), MultiValues::$variant(mut other_values)) => {
55 values.append(&mut other_values);
56 }
57 )+
58 (slot @ MultiValues::Empty(_), other_values) => *slot = other_values,
59 _ => unreachable!(),
60 }
61 };
62}
63
64impl MultiValues {
65 /// Generic constructor method
66 ///
67 /// Creates `MultiValues` from any supported input form, avoiding direct
68 /// use of enum variants at call sites.
69 ///
70 /// Supported input forms include single values, vectors, slices, arrays,
71 /// borrowed vectors, and borrowed string collections for supported element
72 /// types.
73 ///
74 /// # Type Parameters
75 ///
76 /// * `S` - Input type convertible into [`MultiValues`].
77 ///
78 /// # Returns
79 ///
80 /// Returns `MultiValues` wrapping the converted input values.
81 ///
82 /// # Example
83 ///
84 /// ```rust
85 /// use qubit_value::MultiValues;
86 ///
87 /// // Basic types
88 /// let mv = MultiValues::new(vec![1, 2, 3]);
89 /// assert_eq!(mv.count(), 3);
90 ///
91 /// // Strings
92 /// let mv = MultiValues::new(vec!["a".to_string(), "b".to_string()]);
93 /// assert_eq!(mv.count(), 2);
94 /// ```
95 #[inline]
96 pub fn new<S>(values: S) -> Self
97 where
98 S: Into<Self>,
99 {
100 values.into()
101 }
102
103 /// Generic getter method for multiple values.
104 ///
105 /// Performs a strict typed read of all stored values as `Vec<T>`.
106 ///
107 /// # Type Parameters
108 ///
109 /// * `T` - The target element type to retrieve.
110 ///
111 /// # Returns
112 ///
113 /// Returns the list of values when the stored type matches `T`.
114 ///
115 /// # Errors
116 ///
117 /// Returns [`ValueError::TypeMismatch`] when the stored type differs from
118 /// `T`.
119 ///
120 /// # Example
121 ///
122 /// ```rust
123 /// use qubit_value::MultiValues;
124 ///
125 /// let multi = MultiValues::Int32(vec![1, 2, 3]);
126 ///
127 /// // Through type inference
128 /// let nums: Vec<i32> = multi.get().unwrap();
129 /// assert_eq!(nums, vec![1, 2, 3]);
130 ///
131 /// // Explicitly specify type parameter
132 /// let nums = multi.get::<i32>().unwrap();
133 /// assert_eq!(nums, vec![1, 2, 3]);
134 /// ```
135 #[inline]
136 pub fn get<T>(&self) -> ValueResult<Vec<T>>
137 where
138 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
139 {
140 Vec::<T>::try_from(self)
141 }
142
143 /// Generic getter method with a default value list.
144 ///
145 /// Returns the supplied default only when the stored list is empty. Type
146 /// mismatches are still returned as errors.
147 #[inline]
148 pub fn get_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
149 where
150 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
151 {
152 let values = self.get()?;
153 if values.is_empty() {
154 Ok(default.into_value_default())
155 } else {
156 Ok(values)
157 }
158 }
159
160 /// Generic getter method for the first value
161 ///
162 /// Reads the first stored value as `T`, performing strict type checking.
163 ///
164 /// `get_first<T>()` does not do cross-type conversion. Use [`Self::to`] if
165 /// conversion between compatible data types is desired.
166 ///
167 /// # Type Parameters
168 ///
169 /// * `T` - The target element type to retrieve.
170 ///
171 /// # Returns
172 ///
173 /// Returns the first value when the stored type matches `T` and at least
174 /// one value exists.
175 ///
176 /// # Errors
177 ///
178 /// Returns [`ValueError::NoValue`] when the requested type matches but no
179 /// value is stored, or [`ValueError::TypeMismatch`] when the stored type
180 /// differs from `T`.
181 ///
182 /// # Example
183 ///
184 /// ```rust
185 /// use qubit_value::MultiValues;
186 ///
187 /// let multi = MultiValues::Int32(vec![42, 100, 200]);
188 ///
189 /// // Through type inference
190 /// let first: i32 = multi.get_first().unwrap();
191 /// assert_eq!(first, 42);
192 ///
193 /// // Explicitly specify type parameter
194 /// let first = multi.get_first::<i32>().unwrap();
195 /// assert_eq!(first, 42);
196 ///
197 /// // String type
198 /// let multi = MultiValues::String(vec!["hello".to_string(), "world".to_string()]);
199 /// let first: String = multi.get_first().unwrap();
200 /// assert_eq!(first, "hello");
201 /// ```
202 #[inline]
203 pub fn get_first<T>(&self) -> ValueResult<T>
204 where
205 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
206 {
207 T::try_from(self)
208 }
209
210 /// Generic first-value getter with a default value.
211 ///
212 /// Returns the supplied default only when no first value exists. Type
213 /// mismatches are still returned as errors.
214 #[inline]
215 pub fn get_first_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
216 where
217 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
218 {
219 match self.get_first() {
220 Err(ValueError::NoValue) => Ok(default.into_value_default()),
221 result => result,
222 }
223 }
224
225 /// Generic setter method
226 ///
227 /// Replaces the entire list with the converted input values.
228 ///
229 /// This operation updates the stored type to the input element type and
230 /// does not validate runtime compatibility with the previous variant.
231 ///
232 /// Supports any input that can be converted into [`MultiValues`], including
233 /// single values, vectors, slices, arrays, and borrowed vectors for supported
234 /// element types.
235 ///
236 /// Existing values are replaced, and the stored type becomes the converted
237 /// input type.
238 ///
239 /// # Type Parameters
240 ///
241 /// * `S` - Input type convertible into [`MultiValues`].
242 ///
243 /// # Parameters
244 ///
245 /// * `values` - The values to set.
246 ///
247 /// # Returns
248 ///
249 /// Always returns `Ok(())` for supported input types. Unsupported input
250 /// types fail to compile because they do not implement `Into<MultiValues>`.
251 ///
252 /// # Example
253 ///
254 /// ```rust
255 /// use qubit_datatype::DataType;
256 /// use qubit_value::MultiValues;
257 ///
258 /// // 1) Vec<T>
259 /// let mut mv = MultiValues::Empty(DataType::Int32);
260 /// mv.set(vec![42, 100, 200]).unwrap();
261 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200]);
262 ///
263 /// // 2) &[T]
264 /// let mut mv = MultiValues::Empty(DataType::Int32);
265 /// let slice = &[7, 8, 9][..];
266 /// mv.set(slice).unwrap();
267 /// assert_eq!(mv.get_int32s().unwrap(), &[7, 8, 9]);
268 ///
269 /// // 3) Single T
270 /// let mut mv = MultiValues::Empty(DataType::Int32);
271 /// mv.set(42).unwrap();
272 /// assert_eq!(mv.get_int32s().unwrap(), &[42]);
273 ///
274 /// // String example
275 /// let mut mv = MultiValues::Empty(DataType::String);
276 /// mv.set(vec!["hello".to_string(), "world".to_string()]).unwrap();
277 /// assert_eq!(mv.get_strings().unwrap(), &["hello", "world"]);
278 /// ```
279 #[inline]
280 pub fn set<S>(&mut self, values: S) -> ValueResult<()>
281 where
282 S: Into<Self>,
283 {
284 *self = values.into();
285 Ok(())
286 }
287
288 /// Generic add method
289 ///
290 /// Appends converted input values to the existing list with strict type checking.
291 ///
292 /// Supports any input that can be converted into [`MultiValues`], including
293 /// single values, vectors, slices, arrays, and borrowed vectors for supported
294 /// element types.
295 ///
296 /// The converted input must have the same data type as the current container.
297 /// An empty container keeps its declared type until non-empty values of the
298 /// same type are appended.
299 ///
300 /// # Type Parameters
301 ///
302 /// * `S` - Input type convertible into [`MultiValues`].
303 ///
304 /// # Errors
305 ///
306 /// Returns [`ValueError::TypeMismatch`] when the converted input data type
307 /// differs from the current container data type.
308 ///
309 /// # Example
310 ///
311 /// ```rust
312 /// use qubit_datatype::DataType;
313 /// use qubit_value::MultiValues;
314 ///
315 /// // 1) Single T
316 /// let mut mv = MultiValues::Int32(vec![42]);
317 /// mv.add(100).unwrap();
318 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100]);
319 ///
320 /// // 2) Vec<T>
321 /// mv.add(vec![200, 300]).unwrap();
322 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300]);
323 ///
324 /// // 3) &[T]
325 /// let slice = &[400, 500][..];
326 /// mv.add(slice).unwrap();
327 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300, 400, 500]);
328 /// ```
329 #[inline]
330 pub fn add<S>(&mut self, values: S) -> ValueResult<()>
331 where
332 S: Into<Self>,
333 {
334 let other = values.into();
335 if self.data_type() != other.data_type() {
336 return Err(ValueError::TypeMismatch {
337 expected: self.data_type(),
338 actual: other.data_type(),
339 });
340 }
341 if other.count() == 0 {
342 return Ok(());
343 }
344
345 for_each_multi_value_type!(multi_values_append_match, self, other);
346
347 Ok(())
348 }
349
350 /// Get the data type of the values
351 ///
352 /// # Returns
353 ///
354 /// Returns the data type corresponding to these multiple values
355 ///
356 /// # Example
357 ///
358 /// ```rust
359 /// use qubit_datatype::DataType;
360 /// use qubit_value::MultiValues;
361 ///
362 /// let values = MultiValues::Int32(vec![1, 2, 3]);
363 /// assert_eq!(values.data_type(), DataType::Int32);
364 /// ```
365 #[inline]
366 pub fn data_type(&self) -> DataType {
367 for_each_multi_value_type!(multi_values_data_type_match, self)
368 }
369
370 /// Get the number of values
371 ///
372 /// # Returns
373 ///
374 /// Returns the number of values contained in these multiple values
375 ///
376 /// # Example
377 ///
378 /// ```rust
379 /// use qubit_datatype::DataType;
380 /// use qubit_value::MultiValues;
381 ///
382 /// let values = MultiValues::Int32(vec![1, 2, 3]);
383 /// assert_eq!(values.count(), 3);
384 ///
385 /// let empty = MultiValues::Empty(DataType::String);
386 /// assert_eq!(empty.count(), 0);
387 /// ```
388 #[inline]
389 pub fn count(&self) -> usize {
390 for_each_multi_value_type!(multi_values_count_match, self)
391 }
392
393 /// Check if empty
394 ///
395 /// # Returns
396 ///
397 /// Returns `true` if these multiple values do not contain any values
398 ///
399 /// # Example
400 ///
401 /// ```rust
402 /// use qubit_datatype::DataType;
403 /// use qubit_value::MultiValues;
404 ///
405 /// let values = MultiValues::Int32(vec![]);
406 /// assert!(values.is_empty());
407 ///
408 /// let empty = MultiValues::Empty(DataType::String);
409 /// assert!(empty.is_empty());
410 /// ```
411 #[inline]
412 pub fn is_empty(&self) -> bool {
413 self.count() == 0
414 }
415
416 /// Clear all values while preserving the type
417 ///
418 /// # Example
419 ///
420 /// ```rust
421 /// use qubit_datatype::DataType;
422 /// use qubit_value::MultiValues;
423 ///
424 /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
425 /// values.clear();
426 /// assert!(values.is_empty());
427 /// assert_eq!(values.data_type(), DataType::Int32);
428 /// ```
429 #[inline]
430 pub fn clear(&mut self) {
431 for_each_multi_value_type!(multi_values_clear_match, self)
432 }
433
434 /// Set the data type
435 ///
436 /// If the new type differs from the current type, clears all values and
437 /// sets the new type.
438 ///
439 /// # Parameters
440 ///
441 /// * `data_type` - The data type to set
442 ///
443 /// # Example
444 ///
445 /// ```rust
446 /// use qubit_datatype::DataType;
447 /// use qubit_value::MultiValues;
448 ///
449 /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
450 /// values.set_type(DataType::String);
451 /// assert!(values.is_empty());
452 /// assert_eq!(values.data_type(), DataType::String);
453 /// ```
454 #[inline]
455 pub fn set_type(&mut self, data_type: DataType) {
456 if self.data_type() != data_type {
457 *self = MultiValues::Empty(data_type);
458 }
459 }
460}