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}