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}