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;
22use super::multi_values_add_arg::MultiValuesAddArg;
23use super::multi_values_adder::MultiValuesAdder;
24use super::multi_values_constructor_arg::MultiValuesConstructorArg;
25use super::multi_values_first_getter::MultiValuesFirstGetter;
26use super::multi_values_getter::MultiValuesGetter;
27use super::multi_values_multi_adder::MultiValuesMultiAdder;
28use super::multi_values_set_arg::MultiValuesSetArg;
29use super::multi_values_setter::MultiValuesSetter;
30use super::multi_values_setter_slice::MultiValuesSetterSlice;
31use super::multi_values_single_setter::MultiValuesSingleSetter;
32
33macro_rules! multi_values_data_type_match {
34    ($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
35        match $value {
36            MultiValues::Empty(dt) => *dt,
37            $(MultiValues::$variant(_) => $data_type,)+
38        }
39    };
40}
41
42macro_rules! multi_values_count_match {
43    ($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
44        match $value {
45            MultiValues::Empty(_) => 0,
46            $(MultiValues::$variant(values) => values.len(),)+
47        }
48    };
49}
50
51macro_rules! multi_values_clear_match {
52    ($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
53        match $value {
54            MultiValues::Empty(_) => {}
55            $(MultiValues::$variant(values) => values.clear(),)+
56        }
57    };
58}
59
60impl MultiValues {
61    /// Generic constructor method
62    ///
63    /// Creates `MultiValues` from `Vec<T>`, avoiding direct use of enum
64    /// variants.
65    ///
66    /// # Type Parameters
67    ///
68    /// * `T` - Element type
69    ///
70    /// # Returns
71    ///
72    /// Returns `MultiValues` wrapping the given value list
73    ///
74    /// # Example
75    ///
76    /// ```rust
77    /// use qubit_value::MultiValues;
78    ///
79    /// // Basic types
80    /// let mv = MultiValues::new(vec![1, 2, 3]);
81    /// assert_eq!(mv.count(), 3);
82    ///
83    /// // Strings
84    /// let mv = MultiValues::new(vec!["a".to_string(), "b".to_string()]);
85    /// assert_eq!(mv.count(), 2);
86    /// ```
87    #[inline]
88    pub fn new<'a, S>(values: S) -> Self
89    where
90        S: MultiValuesConstructorArg<'a>,
91    {
92        values.into_multi_values()
93    }
94
95    /// Generic getter method for multiple values
96    ///
97    /// Automatically selects the correct getter method based on the target
98    /// type, performing strict type checking.
99    ///
100    /// # Type Parameters
101    ///
102    /// * `T` - The target element type to retrieve.
103    ///
104    /// # Returns
105    ///
106    /// If types match, returns the list of values; otherwise returns an error.
107    ///
108    /// # Example
109    ///
110    /// ```rust
111    /// use qubit_value::MultiValues;
112    ///
113    /// let multi = MultiValues::Int32(vec![1, 2, 3]);
114    ///
115    /// // Through type inference
116    /// let nums: Vec<i32> = multi.get().unwrap();
117    /// assert_eq!(nums, vec![1, 2, 3]);
118    ///
119    /// // Explicitly specify type parameter
120    /// let nums = multi.get::<i32>().unwrap();
121    /// assert_eq!(nums, vec![1, 2, 3]);
122    /// ```
123    #[inline]
124    pub fn get<T>(&self) -> ValueResult<Vec<T>>
125    where
126        Self: MultiValuesGetter<T>,
127    {
128        <Self as MultiValuesGetter<T>>::get_values(self)
129    }
130
131    /// Generic getter method with a default value list.
132    ///
133    /// Returns the supplied default only when the stored list is empty. Type
134    /// mismatches are still returned as errors.
135    #[inline]
136    pub fn get_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
137    where
138        Self: MultiValuesGetter<T>,
139    {
140        let values = self.get()?;
141        if values.is_empty() {
142            Ok(default.into_value_default())
143        } else {
144            Ok(values)
145        }
146    }
147
148    /// Generic getter method for the first value
149    ///
150    /// Automatically selects the correct getter method based on the target type,
151    /// performing strict type checking.
152    ///
153    /// # Type Parameters
154    ///
155    /// * `T` - The target element type to retrieve.
156    ///
157    /// # Returns
158    ///
159    /// If types match and a value exists, returns the first value; otherwise
160    /// returns an error.
161    ///
162    /// # Example
163    ///
164    /// ```rust
165    /// use qubit_value::MultiValues;
166    ///
167    /// let multi = MultiValues::Int32(vec![42, 100, 200]);
168    ///
169    /// // Through type inference
170    /// let first: i32 = multi.get_first().unwrap();
171    /// assert_eq!(first, 42);
172    ///
173    /// // Explicitly specify type parameter
174    /// let first = multi.get_first::<i32>().unwrap();
175    /// assert_eq!(first, 42);
176    ///
177    /// // String type
178    /// let multi = MultiValues::String(vec!["hello".to_string(), "world".to_string()]);
179    /// let first: String = multi.get_first().unwrap();
180    /// assert_eq!(first, "hello");
181    /// ```
182    #[inline]
183    pub fn get_first<T>(&self) -> ValueResult<T>
184    where
185        Self: MultiValuesFirstGetter<T>,
186    {
187        <Self as MultiValuesFirstGetter<T>>::get_first_value(self)
188    }
189
190    /// Generic first-value getter with a default value.
191    ///
192    /// Returns the supplied default only when no first value exists. Type
193    /// mismatches are still returned as errors.
194    #[inline]
195    pub fn get_first_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
196    where
197        Self: MultiValuesFirstGetter<T>,
198    {
199        match self.get_first() {
200            Err(ValueError::NoValue) => Ok(default.into_value_default()),
201            result => result,
202        }
203    }
204
205    /// Generic setter method
206    ///
207    /// Automatically selects the optimal setter path based on the input type,
208    /// replacing the entire list.
209    ///
210    /// This operation updates the stored type to the input element type and
211    /// does not validate runtime compatibility with the previous variant.
212    ///
213    /// Supports three input forms, all unified to this method via internal
214    /// dispatch traits:
215    ///
216    /// - `Vec<T>`: Takes `set_values(Vec<T>)` path with zero additional allocation
217    /// - `&[T]`: Takes `set_values_slice(&[T])` path
218    /// - `T`: Takes `set_single_value(T)` path
219    ///
220    /// # Type Parameters
221    ///
222    /// * `S` - Input type, can be `Vec<T>`, `&[T]`, or a single `T`
223    ///
224    /// # Parameters
225    ///
226    /// * `values` - The value collection to set, can be `Vec<T>`, `&[T]`, or a
227    ///   single `T`
228    ///
229    /// # Returns
230    ///
231    /// If setting succeeds, returns `Ok(())`; otherwise returns an error.
232    ///
233    /// # Example
234    ///
235    /// ```rust
236    /// use qubit_datatype::DataType;
237    /// use qubit_value::MultiValues;
238    ///
239    /// // 1) Vec<T>
240    /// let mut mv = MultiValues::Empty(DataType::Int32);
241    /// mv.set(vec![42, 100, 200]).unwrap();
242    /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200]);
243    ///
244    /// // 2) &[T]
245    /// let mut mv = MultiValues::Empty(DataType::Int32);
246    /// let slice = &[7, 8, 9][..];
247    /// mv.set(slice).unwrap();
248    /// assert_eq!(mv.get_int32s().unwrap(), &[7, 8, 9]);
249    ///
250    /// // 3) Single T
251    /// let mut mv = MultiValues::Empty(DataType::Int32);
252    /// mv.set(42).unwrap();
253    /// assert_eq!(mv.get_int32s().unwrap(), &[42]);
254    ///
255    /// // String example
256    /// let mut mv = MultiValues::Empty(DataType::String);
257    /// mv.set(vec!["hello".to_string(), "world".to_string()]).unwrap();
258    /// assert_eq!(mv.get_strings().unwrap(), &["hello", "world"]);
259    /// ```
260    #[inline]
261    pub fn set<'a, S>(&mut self, values: S) -> ValueResult<()>
262    where
263        S: MultiValuesSetArg<'a>,
264        Self: MultiValuesSetter<S::Item>
265            + MultiValuesSetterSlice<S::Item>
266            + MultiValuesSingleSetter<S::Item>,
267    {
268        values.apply(self)
269    }
270
271    /// Generic add method
272    ///
273    /// Automatically selects the optimal add path based on the input type,
274    /// appending elements to the existing list with strict type checking.
275    ///
276    /// Supports three input forms:
277    ///
278    /// - `T`: Takes `add_value(T)` path, appending a single element
279    /// - `Vec<T>`: Takes `add_values(Vec<T>)` path, batch append (zero additional allocation)
280    /// - `&[T]`: Takes `add_values_slice(&[T])` path, batch append (using slice)
281    ///
282    /// # Type Parameters
283    ///
284    /// * `S` - Input type, can be a single `T`, `Vec<T>`, or `&[T]`
285    ///
286    /// # Example
287    ///
288    /// ```rust
289    /// use qubit_datatype::DataType;
290    /// use qubit_value::MultiValues;
291    ///
292    /// // 1) Single T
293    /// let mut mv = MultiValues::Int32(vec![42]);
294    /// mv.add(100).unwrap();
295    /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100]);
296    ///
297    /// // 2) Vec<T>
298    /// mv.add(vec![200, 300]).unwrap();
299    /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300]);
300    ///
301    /// // 3) &[T]
302    /// let slice = &[400, 500][..];
303    /// mv.add(slice).unwrap();
304    /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300, 400, 500]);
305    /// ```
306    #[inline]
307    pub fn add<'a, S>(&mut self, values: S) -> ValueResult<()>
308    where
309        S: MultiValuesAddArg<'a>,
310        Self: MultiValuesAdder<S::Item> + MultiValuesMultiAdder<S::Item>,
311    {
312        values.apply_add(self)
313    }
314
315    /// Get the data type of the values
316    ///
317    /// # Returns
318    ///
319    /// Returns the data type corresponding to these multiple values
320    ///
321    /// # Example
322    ///
323    /// ```rust
324    /// use qubit_datatype::DataType;
325    /// use qubit_value::MultiValues;
326    ///
327    /// let values = MultiValues::Int32(vec![1, 2, 3]);
328    /// assert_eq!(values.data_type(), DataType::Int32);
329    /// ```
330    #[inline]
331    pub fn data_type(&self) -> DataType {
332        for_each_multi_value_type!(multi_values_data_type_match, self)
333    }
334
335    /// Get the number of values
336    ///
337    /// # Returns
338    ///
339    /// Returns the number of values contained in these multiple values
340    ///
341    /// # Example
342    ///
343    /// ```rust
344    /// use qubit_datatype::DataType;
345    /// use qubit_value::MultiValues;
346    ///
347    /// let values = MultiValues::Int32(vec![1, 2, 3]);
348    /// assert_eq!(values.count(), 3);
349    ///
350    /// let empty = MultiValues::Empty(DataType::String);
351    /// assert_eq!(empty.count(), 0);
352    /// ```
353    #[inline]
354    pub fn count(&self) -> usize {
355        for_each_multi_value_type!(multi_values_count_match, self)
356    }
357
358    /// Check if empty
359    ///
360    /// # Returns
361    ///
362    /// Returns `true` if these multiple values do not contain any values
363    ///
364    /// # Example
365    ///
366    /// ```rust
367    /// use qubit_datatype::DataType;
368    /// use qubit_value::MultiValues;
369    ///
370    /// let values = MultiValues::Int32(vec![]);
371    /// assert!(values.is_empty());
372    ///
373    /// let empty = MultiValues::Empty(DataType::String);
374    /// assert!(empty.is_empty());
375    /// ```
376    #[inline]
377    pub fn is_empty(&self) -> bool {
378        self.count() == 0
379    }
380
381    /// Clear all values while preserving the type
382    ///
383    /// # Example
384    ///
385    /// ```rust
386    /// use qubit_datatype::DataType;
387    /// use qubit_value::MultiValues;
388    ///
389    /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
390    /// values.clear();
391    /// assert!(values.is_empty());
392    /// assert_eq!(values.data_type(), DataType::Int32);
393    /// ```
394    #[inline]
395    pub fn clear(&mut self) {
396        for_each_multi_value_type!(multi_values_clear_match, self)
397    }
398
399    /// Set the data type
400    ///
401    /// If the new type differs from the current type, clears all values and
402    /// sets the new type.
403    ///
404    /// # Parameters
405    ///
406    /// * `data_type` - The data type to set
407    ///
408    /// # Example
409    ///
410    /// ```rust
411    /// use qubit_datatype::DataType;
412    /// use qubit_value::MultiValues;
413    ///
414    /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
415    /// values.set_type(DataType::String);
416    /// assert!(values.is_empty());
417    /// assert_eq!(values.data_type(), DataType::String);
418    /// ```
419    #[inline]
420    pub fn set_type(&mut self, data_type: DataType) {
421        if self.data_type() != data_type {
422            *self = MultiValues::Empty(data_type);
423        }
424    }
425}