Skip to main content

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}