Skip to main content

qubit_value/multi_values/
multi_values.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//! # Multiple Values Container
11//!
12//! Provides type-safe storage and access functionality for multiple values.
13//!
14
15use bigdecimal::BigDecimal;
16use chrono::{
17    DateTime,
18    NaiveDate,
19    NaiveDateTime,
20    NaiveTime,
21    Utc,
22};
23use num_bigint::BigInt;
24use serde::{
25    Deserialize,
26    Serialize,
27};
28use std::collections::HashMap;
29use std::time::Duration;
30use url::Url;
31
32use qubit_datatype::DataType;
33
34/// Multiple values container
35///
36/// Uses an enum to represent multiple values of different types, providing
37/// type-safe storage and access for multiple values.
38///
39/// # Features
40///
41/// - Supports collections of multiple basic data types.
42/// - Provides two sets of APIs for type checking and type conversion.
43/// - Supports unified access to single and multiple values.
44/// - Automatic memory management.
45///
46/// # Example
47///
48/// ```rust
49/// use qubit_value::MultiValues;
50///
51/// // Create integer multiple values
52/// let mut values = MultiValues::Int32(vec![1, 2, 3]);
53/// assert_eq!(values.count(), 3);
54/// assert_eq!(values.get_first_int32().unwrap(), 1);
55///
56/// // Get all values
57/// let all = values.get_int32s().unwrap();
58/// assert_eq!(all, &[1, 2, 3]);
59///
60/// // Use generic method to add value
61/// values.add(4).unwrap();
62/// assert_eq!(values.count(), 4);
63/// ```
64///
65///
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub enum MultiValues {
68    /// Empty value (has type but no values)
69    Empty(DataType),
70    /// Boolean value list
71    Bool(Vec<bool>),
72    /// Character value list
73    Char(Vec<char>),
74    /// i8 list
75    Int8(Vec<i8>),
76    /// i16 list
77    Int16(Vec<i16>),
78    /// i32 list
79    Int32(Vec<i32>),
80    /// i64 list
81    Int64(Vec<i64>),
82    /// i128 list
83    Int128(Vec<i128>),
84    /// u8 list
85    UInt8(Vec<u8>),
86    /// u16 list
87    UInt16(Vec<u16>),
88    /// u32 list
89    UInt32(Vec<u32>),
90    /// u64 list
91    UInt64(Vec<u64>),
92    /// u128 list
93    UInt128(Vec<u128>),
94    /// isize list
95    IntSize(Vec<isize>),
96    /// usize list
97    UIntSize(Vec<usize>),
98    /// f32 list
99    Float32(Vec<f32>),
100    /// f64 list
101    Float64(Vec<f64>),
102    /// Big integer list
103    BigInteger(Vec<BigInt>),
104    /// Big decimal list
105    BigDecimal(Vec<BigDecimal>),
106    /// String list
107    String(Vec<String>),
108    /// Date list
109    Date(Vec<NaiveDate>),
110    /// Time list
111    Time(Vec<NaiveTime>),
112    /// DateTime list
113    DateTime(Vec<NaiveDateTime>),
114    /// UTC instant list
115    Instant(Vec<DateTime<Utc>>),
116    /// Duration list
117    Duration(Vec<Duration>),
118    /// Url list
119    Url(Vec<Url>),
120    /// StringMap list
121    StringMap(Vec<HashMap<String, String>>),
122    /// Json list
123    Json(Vec<serde_json::Value>),
124}
125
126// ============================================================================
127// Getter method generation macros
128// ============================================================================
129
130/// Unified multiple values getter generation macro
131///
132/// Generates `get_[xxx]s` methods for `MultiValues`, returning a reference to
133/// value slices.
134///
135/// # Documentation Comment Support
136///
137/// The macro automatically extracts preceding documentation comments, so you
138/// can add `///` comments before macro invocations.
139///
140///
141macro_rules! impl_get_multi_values {
142    // Simple type: return slice reference
143    ($(#[$attr:meta])* slice: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
144        $(#[$attr])*
145        #[inline]
146        pub fn $method(&self) -> ValueResult<&[$type]> {
147            match self {
148                MultiValues::$variant(v) => Ok(v),
149                MultiValues::Empty(dt) if *dt == $data_type => Ok(&[]),
150                _ => Err(ValueError::TypeMismatch {
151                    expected: $data_type,
152                    actual: self.data_type(),
153                }),
154            }
155        }
156    };
157
158    // Complex type: return Vec reference (e.g., Vec<String>, Vec<Vec<u8>>)
159    ($(#[$attr:meta])* vec: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
160        $(#[$attr])*
161        #[inline]
162        pub fn $method(&self) -> ValueResult<&[$type]> {
163            match self {
164                MultiValues::$variant(v) => Ok(v.as_slice()),
165                MultiValues::Empty(dt) if *dt == $data_type => Ok(&[]),
166                _ => Err(ValueError::TypeMismatch {
167                    expected: $data_type,
168                    actual: self.data_type(),
169                }),
170            }
171        }
172    };
173}
174
175/// Unified multiple values get_first method generation macro
176///
177/// Generates `get_first_[xxx]` methods for `MultiValues`, used to get the first
178/// value.
179///
180/// # Documentation Comment Support
181///
182/// The macro automatically extracts preceding documentation comments, so you
183/// can add `///` comments before macro invocations.
184///
185///
186macro_rules! impl_get_first_value {
187    // Copy type: directly return value
188    ($(#[$attr:meta])* copy: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
189        $(#[$attr])*
190        #[inline]
191        pub fn $method(&self) -> ValueResult<$type> {
192            match self {
193                MultiValues::$variant(v) if !v.is_empty() => Ok(v[0]),
194                MultiValues::$variant(_) => Err(ValueError::NoValue),
195                MultiValues::Empty(dt) if *dt == $data_type => Err(ValueError::NoValue),
196                _ => Err(ValueError::TypeMismatch {
197                    expected: $data_type,
198                    actual: self.data_type(),
199                }),
200            }
201        }
202    };
203
204    // Reference type: return reference
205    ($(#[$attr:meta])* ref: $method:ident, $variant:ident, $ret_type:ty, $data_type:expr, $conversion:expr) => {
206        $(#[$attr])*
207        #[inline]
208        pub fn $method(&self) -> ValueResult<$ret_type> {
209            match self {
210                MultiValues::$variant(v) if !v.is_empty() => {
211                    let conv_fn: fn(&_) -> $ret_type = $conversion;
212                    Ok(conv_fn(&v[0]))
213                },
214                MultiValues::$variant(_) => Err(ValueError::NoValue),
215                MultiValues::Empty(dt) if *dt == $data_type => Err(ValueError::NoValue),
216                _ => Err(ValueError::TypeMismatch {
217                    expected: $data_type,
218                    actual: self.data_type(),
219                }),
220            }
221        }
222    };
223}
224
225/// Unified multiple values add method generation macro
226///
227/// Generates `add_[xxx]` methods for `MultiValues`, used to add a single value.
228///
229/// # Documentation Comment Support
230///
231/// The macro automatically extracts preceding documentation comments, so you
232/// can add `///` comments before macro invocations.
233///
234///
235macro_rules! impl_add_single_value {
236    ($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
237        $(#[$attr])*
238        #[inline]
239        pub fn $method(&mut self, value: $type) -> ValueResult<()> {
240            match self {
241                MultiValues::$variant(v) => {
242                    v.push(value);
243                    Ok(())
244                }
245                MultiValues::Empty(dt) if *dt == $data_type => {
246                    *self = MultiValues::$variant(vec![value]);
247                    Ok(())
248                }
249                _ => Err(ValueError::TypeMismatch {
250                    expected: $data_type,
251                    actual: self.data_type(),
252                }),
253            }
254        }
255    };
256}
257
258/// Unified multiple values add multiple method generation macro
259///
260/// Generates `add_[xxx]s` methods for `MultiValues`, used to add multiple values.
261///
262/// # Documentation Comment Support
263///
264/// The macro automatically extracts preceding documentation comments, so you
265/// can add `///` comments before macro invocations.
266///
267///
268macro_rules! impl_add_multi_values {
269    ($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
270        $(#[$attr])*
271        #[inline]
272        pub fn $method(&mut self, values: Vec<$type>) -> ValueResult<()> {
273            match self {
274                MultiValues::$variant(v) => {
275                    v.extend(values);
276                    Ok(())
277                }
278                MultiValues::Empty(dt) if *dt == $data_type => {
279                    *self = MultiValues::$variant(values);
280                    Ok(())
281                }
282                _ => Err(ValueError::TypeMismatch {
283                    expected: $data_type,
284                    actual: self.data_type(),
285                }),
286            }
287        }
288    };
289}
290
291/// Unified multiple values add from slice method generation macro
292///
293/// Generates `add_[xxx]s_slice` methods for `MultiValues`, used to append
294/// multiple values at once from a slice.
295///
296///
297macro_rules! impl_add_multi_values_slice {
298    ($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
299        $(#[$attr])*
300        #[inline]
301        pub fn $method(&mut self, values: &[$type]) -> ValueResult<()> {
302            match self {
303                MultiValues::$variant(v) => {
304                    v.extend_from_slice(values);
305                    Ok(())
306                }
307                MultiValues::Empty(dt) if *dt == $data_type => {
308                    *self = MultiValues::$variant(values.to_vec());
309                    Ok(())
310                }
311                _ => Err(ValueError::TypeMismatch {
312                    expected: $data_type,
313                    actual: self.data_type(),
314                }),
315            }
316        }
317    };
318}
319
320/// Unified multiple values single value set method generation macro
321///
322/// Generates `set_[xxx]` methods for `MultiValues`, used to set a single value
323/// (replacing the entire list).
324///
325/// # Documentation Comment Support
326///
327/// The macro automatically extracts preceding documentation comments, so you
328/// can add `///` comments before macro invocations.
329///
330///
331macro_rules! impl_set_single_value {
332    ($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
333        $(#[$attr])*
334        pub fn $method(&mut self, value: $type) -> ValueResult<()> {
335            *self = MultiValues::$variant(vec![value]);
336            Ok(())
337        }
338    };
339}
340
341/// Unified multiple values set method generation macro
342///
343/// Generates `set_[xxx]s` methods for `MultiValues`, used to set the entire
344/// value list.
345///
346/// # Documentation Comment Support
347///
348/// The macro automatically extracts preceding documentation comments, so you
349/// can add `///` comments before macro invocations.
350///
351///
352macro_rules! impl_set_multi_values {
353    ($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
354        $(#[$attr])*
355        pub fn $method(&mut self, values: Vec<$type>) -> ValueResult<()> {
356            *self = MultiValues::$variant(values);
357            Ok(())
358        }
359    };
360}
361
362/// Unified multiple values set (slice) method generation macro
363///
364/// Generates `set_[xxx]s_slice` methods for `MultiValues`, used to set the
365/// entire value list from a slice.
366///
367/// This method directly replaces the internally stored list without type
368/// matching checks, behaving consistently with `set_[xxx]s`.
369///
370/// # Documentation Comment Support
371///
372/// The macro automatically extracts preceding documentation comments, so you
373/// can add `///` comments before macro invocations.
374///
375///
376macro_rules! impl_set_multi_values_slice {
377    ($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
378        $(#[$attr])*
379        pub fn $method(&mut self, values: &[$type]) -> ValueResult<()> {
380            *self = MultiValues::$variant(values.to_vec());
381            Ok(())
382        }
383    };
384}