qubit_value/multi_values/multi_values.rs
1// =============================================================================
2// Copyright (c) 2025 - 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! # Multiple Values Container
9//!
10//! Provides type-safe storage and access functionality for multiple values.
11// qubit-style: allow source-test-pair
12// Tests are intentionally distributed across behavior-specific files under
13// tests/multi_values/ rather than collected in multi_values_tests.rs.
14// qubit-style: allow multiple-public-types
15use std::collections::HashMap;
16use std::fmt;
17#[cfg(feature = "json")]
18use std::hash::Hash;
19#[cfg(feature = "json")]
20use std::hash::Hasher;
21use std::time::Duration;
22
23#[cfg(feature = "big-decimal")]
24use bigdecimal::BigDecimal;
25#[cfg(feature = "chrono")]
26use chrono::DateTime;
27#[cfg(feature = "chrono")]
28use chrono::NaiveDate;
29#[cfg(feature = "chrono")]
30use chrono::NaiveDateTime;
31#[cfg(feature = "chrono")]
32use chrono::NaiveTime;
33#[cfg(feature = "chrono")]
34use chrono::Utc;
35#[cfg(feature = "big-integer")]
36use num_bigint::BigInt;
37#[cfg(feature = "json")]
38use qubit_budget::MeasuredBudgetError;
39#[cfg(feature = "json")]
40use qubit_budget::ResourceQuantity;
41#[cfg(feature = "json")]
42use qubit_budget::json::JsonValueBudget;
43#[cfg(feature = "converter")]
44use qubit_datatype::ConversionLimits;
45#[cfg(feature = "converter")]
46use qubit_datatype::ConversionPolicy;
47#[cfg(feature = "converter")]
48use qubit_datatype::ConversionSession;
49#[cfg(feature = "converter")]
50use qubit_datatype::DataConversionError;
51#[cfg(feature = "converter")]
52use qubit_datatype::DataConversionTarget;
53#[cfg(feature = "converter")]
54use qubit_datatype::DataConverter;
55#[cfg(feature = "converter")]
56use qubit_datatype::DataConverters;
57use qubit_datatype::DataType;
58#[cfg(feature = "url")]
59use url::Url;
60
61use super::internal::MultiValuesRepr;
62#[cfg(feature = "json")]
63use super::multi_values_identity::hash_multi_values_payload_with_json_budget;
64use super::multi_values_ref::MultiValuesRef;
65use crate::IntoValueDefault;
66use crate::Value;
67use crate::ValueError;
68use crate::ValueResult;
69#[cfg(feature = "json")]
70use crate::identity::hash_json;
71#[cfg(feature = "json")]
72use crate::identity::preflight_json;
73use crate::value::ValueRepr;
74
75/// Multiple typed runtime values with private storage representation.
76///
77/// # Examples
78///
79/// ```
80/// use qubit_value::MultiValues;
81///
82/// let values = MultiValues::from(vec![1_i32, 2, 3]);
83/// assert_eq!(values.get_int32s().unwrap(), &[1, 2, 3]);
84/// ```
85#[must_use]
86#[derive(Clone)]
87pub struct MultiValues {
88 /// Private homogeneous storage backing the stable public accessor API.
89 pub(crate) repr: MultiValuesRepr,
90}
91
92impl fmt::Debug for MultiValues {
93 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
94 self.view().fmt(formatter)
95 }
96}
97
98/// Implements named collection constructors from the shared value table.
99macro_rules! impl_multi_values_constructors {
100 (
101 ;
102 $(
103 (
104 [$($cfg:meta),*],
105 $variant:ident,
106 $type:ty,
107 $data_type:expr,
108 $materialization:ident,
109 $json_class:ident,
110 $number_projection:ident,
111 $value_doc:literal,
112 $multi_doc:literal
113 $(, $_wire:tt)*
114 )
115 ),+ $(,)?
116 ) => {
117 impl MultiValues {
118 /// Creates an unset collection with an explicit element type.
119 ///
120 /// # Parameters
121 ///
122 /// * `data_type` - Element type retained while the collection is unset.
123 ///
124 /// # Returns
125 ///
126 /// An unset collection retaining `data_type`.
127 #[allow(non_snake_case)]
128 #[inline(always)]
129 pub const fn Unset(data_type: DataType) -> Self {
130 Self::new_unset(data_type)
131 }
132
133 /// Creates an unset collection with an explicit element type.
134 ///
135 /// # Parameters
136 ///
137 /// * `data_type` - Element type retained while the collection is unset.
138 ///
139 /// # Returns
140 ///
141 /// An unset collection retaining `data_type`.
142 #[inline(always)]
143 pub const fn new_unset(data_type: DataType) -> Self {
144 Self { repr: MultiValuesRepr::Unset(data_type) }
145 }
146
147 $(
148 #[doc = concat!("Creates a collection of ", $multi_doc, ".")]
149 ///
150 /// # Parameters
151 ///
152 /// * `values` - Homogeneous elements stored by the collection.
153 ///
154 /// # Returns
155 ///
156 /// A typed collection containing `values` in their original order.
157 $(#[$cfg])*
158 #[allow(non_snake_case)]
159 #[inline(always)]
160 pub fn $variant(values: Vec<$type>) -> Self {
161 Self { repr: MultiValuesRepr::$variant(values) }
162 }
163 )+
164 }
165 };
166}
167
168/// Borrows owned storage through the shared type table.
169macro_rules! owned_view_match {
170 ($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
171 match &$value.repr {
172 MultiValuesRepr::Unset(data_type) => MultiValuesRef::Unset(*data_type),
173 $($(#[$cfg])* MultiValuesRepr::$variant(value) => MultiValuesRef::$variant(
174 value.as_slice()
175 ),)+
176 }
177 };
178}
179
180for_each_value_type!(impl_multi_values_constructors);
181
182impl MultiValues {
183 /// Strictly borrows the first stored item without allocating.
184 #[must_use = "the borrowed first-value result should be handled"]
185 #[inline(always)]
186 pub fn get_first_ref<'a, T: ?Sized>(&'a self) -> ValueResult<&'a T>
187 where
188 &'a T: TryFrom<&'a Self, Error = ValueError>,
189 {
190 <&'a T>::try_from(self)
191 }
192
193 /// Strictly borrows the complete collection without allocating.
194 #[must_use = "the borrowed collection result should be handled"]
195 #[inline(always)]
196 pub fn get_slice<'a, T>(&'a self) -> ValueResult<&'a [T]>
197 where
198 &'a [T]: TryFrom<&'a Self, Error = ValueError>,
199 {
200 <&'a [T]>::try_from(self)
201 }
202
203 /// Hashes this collection while applying `budget` to JSON elements.
204 ///
205 /// # Type Parameters
206 ///
207 /// * `H` - Hasher receiving the semantic collection identity.
208 /// * `R` - Resource identifier used by the JSON budget.
209 /// * `Q` - Quantity type used by the JSON budget.
210 ///
211 /// # Parameters
212 ///
213 /// * `state` - Hasher that receives the same identity representation as
214 /// [`Hash::hash`].
215 /// * `budget` - Mutable JSON traversal budget, used only for JSON elements.
216 ///
217 /// # Returns
218 ///
219 /// `Ok(())` after the complete semantic identity is hashed.
220 ///
221 /// # Errors
222 ///
223 /// Returns [`qubit_budget::MeasuredBudgetError`] when a JSON element
224 /// exceeds a configured limit.
225 /// On error, neither `state` nor the committed portion of `budget` is
226 /// modified. A hasher panic also drops the staged budget transaction.
227 ///
228 /// # Examples
229 ///
230 /// ```
231 /// use std::collections::hash_map::DefaultHasher;
232 ///
233 /// use qubit_budget::{ResourceLimit, StructureLimits};
234 /// use qubit_budget::json::{JsonResource, JsonValueBudget, JsonValueLimits};
235 /// use qubit_value::MultiValues;
236 ///
237 /// let values = MultiValues::Json(vec![serde_json::json!([null])]);
238 /// let structure = StructureLimits::<JsonResource, usize>::builder().nodes_limit(
239 /// ResourceLimit::new(JsonResource::Nodes, 1_usize),
240 /// ).build();
241 /// let mut budget = JsonValueBudget::new(
242 /// JsonValueLimits::builder().structure_limits(structure).build(),
243 /// );
244 /// let mut hasher = DefaultHasher::new();
245 ///
246 /// assert!(values.hash_with_json_budget(&mut hasher, &mut budget).is_err());
247 /// drop(hasher);
248 /// // The rejected values did not consume committed budget state.
249 /// ```
250 #[cfg(feature = "json")]
251 pub fn hash_with_json_budget<H, R, Q>(
252 &self,
253 state: &mut H,
254 budget: &mut JsonValueBudget<R, Q>,
255 ) -> Result<(), MeasuredBudgetError<R, Q>>
256 where
257 H: Hasher,
258 R: Clone,
259 Q: ResourceQuantity,
260 {
261 match &self.repr {
262 MultiValuesRepr::Json(values) => {
263 let mut transaction = budget.transaction();
264 for value in values {
265 preflight_json(value, &mut transaction)?;
266 }
267 std::mem::discriminant(&self.repr).hash(state);
268 values.len().hash(state);
269 for value in values {
270 hash_json(value, state);
271 }
272 transaction.commit()
273 }
274 _ => {
275 std::mem::discriminant(&self.repr).hash(state);
276 hash_multi_values_payload_with_json_budget(&self.repr, state, budget)
277 }
278 }
279 }
280
281 /// Borrows the stable semantic view of this collection.
282 ///
283 /// # Returns
284 ///
285 /// A non-owning homogeneous view that hides private storage details.
286 #[must_use = "the borrowed collection view should be used"]
287 #[inline(always)]
288 pub fn view(&self) -> MultiValuesRef<'_> {
289 for_each_value_type!(owned_view_match, self)
290 }
291}
292
293// ============================================================================
294// Getter method generation macros
295// ============================================================================
296
297/// Unified multiple values getter generation macro
298///
299/// Generates `get_[xxx]s` methods for `MultiValues`, returning a reference to
300/// value slices.
301///
302/// # Documentation Comment Support
303///
304/// The macro automatically extracts preceding documentation comments, so you
305/// can add `///` comments before macro invocations.
306macro_rules! impl_get_multi_values {
307 // Simple type: return slice reference
308 ($(#[$attr:meta])* slice: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
309 $(#[$attr])*
310 #[doc = ""]
311 #[doc = "# Errors"]
312 #[doc = ""]
313 #[doc = "Returns [`ValueError::Missing`] when the container is unset"]
314 #[doc = "with the requested type, or [`ValueError::TypeMismatch`] when"]
315 #[doc = "the stored data type differs. A concrete empty vector returns"]
316 #[doc = "an empty slice."]
317 #[must_use = "the strict collection read result should be handled"]
318 #[inline(always)]
319 pub fn $method(&self) -> ValueResult<&[$type]> {
320 match &self.repr {
321 MultiValuesRepr::$variant(v) => Ok(v),
322 MultiValuesRepr::Unset(dt) if *dt == $data_type => {
323 Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *dt)))
324 }
325 _ => Err(ValueError::TypeMismatch {
326 expected: $data_type,
327 actual: self.data_type(),
328 }),
329 }
330 }
331 };
332
333 // Complex type: return Vec reference (e.g., Vec<String>, Vec<Vec<u8>>)
334 ($(#[$attr:meta])* vec: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
335 $(#[$attr])*
336 #[doc = ""]
337 #[doc = "# Errors"]
338 #[doc = ""]
339 #[doc = "Returns [`ValueError::Missing`] when the container is unset"]
340 #[doc = "with the requested type, or [`ValueError::TypeMismatch`] when"]
341 #[doc = "the stored data type differs. A concrete empty vector returns"]
342 #[doc = "an empty slice."]
343 #[must_use = "the strict collection read result should be handled"]
344 #[inline(always)]
345 pub fn $method(&self) -> ValueResult<&[$type]> {
346 match &self.repr {
347 MultiValuesRepr::$variant(v) => Ok(v.as_slice()),
348 MultiValuesRepr::Unset(dt) if *dt == $data_type => {
349 Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *dt)))
350 }
351 _ => Err(ValueError::TypeMismatch {
352 expected: $data_type,
353 actual: self.data_type(),
354 }),
355 }
356 }
357 };
358}
359
360/// Unified multiple values get_first method generation macro
361///
362/// Generates `get_first_[xxx]` methods for `MultiValues`, used to get the first
363/// value.
364///
365/// # Documentation Comment Support
366///
367/// The macro automatically extracts preceding documentation comments, so you
368/// can add `///` comments before macro invocations.
369macro_rules! impl_get_first_value {
370 // Copy type: directly return value
371 ($(#[$attr:meta])* copy: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
372 $(#[$attr])*
373 #[doc = ""]
374 #[doc = "# Errors"]
375 #[doc = ""]
376 #[doc = "Returns [`ValueError::Missing`] when the requested type matches"]
377 #[doc = "but no value is stored, or [`ValueError::TypeMismatch`] when"]
378 #[doc = "the stored data type differs."]
379 #[must_use = "the strict first-value result should be handled"]
380 #[inline(always)]
381 pub fn $method(&self) -> ValueResult<$type> {
382 match &self.repr {
383 MultiValuesRepr::$variant(v) if !v.is_empty() => Ok(v[0]),
384 MultiValuesRepr::$variant(_) => {
385 Err(ValueError::Missing($crate::ValueMissing::empty_collection($data_type, $data_type)))
386 }
387 MultiValuesRepr::Unset(dt) if *dt == $data_type => {
388 Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *dt)))
389 }
390 _ => Err(ValueError::TypeMismatch {
391 expected: $data_type,
392 actual: self.data_type(),
393 }),
394 }
395 }
396 };
397
398 // Reference type: return reference
399 ($(#[$attr:meta])* ref: $method:ident, $variant:ident, $ret_type:ty, $data_type:expr, $conversion:expr) => {
400 $(#[$attr])*
401 #[doc = ""]
402 #[doc = "# Errors"]
403 #[doc = ""]
404 #[doc = "Returns [`ValueError::Missing`] when the requested type matches"]
405 #[doc = "but no value is stored, or [`ValueError::TypeMismatch`] when"]
406 #[doc = "the stored data type differs."]
407 #[must_use = "the strict first-value result should be handled"]
408 #[inline(always)]
409 pub fn $method(&self) -> ValueResult<$ret_type> {
410 match &self.repr {
411 MultiValuesRepr::$variant(v) if !v.is_empty() => {
412 let conv_fn: fn(&_) -> $ret_type = $conversion;
413 Ok(conv_fn(&v[0]))
414 },
415 MultiValuesRepr::$variant(_) => {
416 Err(ValueError::Missing($crate::ValueMissing::empty_collection($data_type, $data_type)))
417 }
418 MultiValuesRepr::Unset(dt) if *dt == $data_type => {
419 Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *dt)))
420 }
421 _ => Err(ValueError::TypeMismatch {
422 expected: $data_type,
423 actual: self.data_type(),
424 }),
425 }
426 }
427 };
428}
429
430#[cfg(all(feature = "converter", feature = "json"))]
431impl MultiValues {
432 /// Projects this collection to its natural JSON representation.
433 ///
434 /// Unset is `null`; every concrete collection is an array, including empty
435 /// and one-item collections.
436 ///
437 /// # Returns
438 ///
439 /// The natural JSON representation of this collection.
440 ///
441 /// # Errors
442 ///
443 /// Returns a list conversion error containing the zero-based source index
444 /// when an item cannot be represented as JSON.
445 #[inline(always)]
446 pub fn to_json_value(&self) -> ValueResult<serde_json::Value> {
447 self.to_json_value_with(ConversionPolicy::default_ref(), ConversionLimits::default_ref())
448 }
449
450 /// Projects this collection using explicit conversion policy and limits.
451 ///
452 /// # Parameters
453 ///
454 /// * `policy` - Controls duration units and precision-loss behavior.
455 /// * `limits` - Bounds conversion resource consumption.
456 ///
457 /// # Returns
458 ///
459 /// The natural JSON representation of this collection.
460 ///
461 /// # Errors
462 ///
463 /// Returns an indexed list conversion error when an item cannot be
464 /// represented under the requested policy and limits.
465 #[inline(always)]
466 pub fn to_json_value_with(
467 &self,
468 policy: &ConversionPolicy,
469 limits: &ConversionLimits,
470 ) -> ValueResult<serde_json::Value> {
471 crate::json::multi_values_to_json_value_with(self, policy, limits)
472 }
473}
474
475/// Maps private collection storage variants to their runtime data types.
476macro_rules! multi_values_data_type_match {
477 ($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
478 match &$value.repr {
479 MultiValuesRepr::Unset(dt) => *dt,
480 $($(#[$cfg])* MultiValuesRepr::$variant(_) => $data_type,)+
481 }
482 };
483}
484
485/// Returns the concrete element count for each collection storage variant.
486macro_rules! multi_values_count_match {
487 ($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
488 match &$value.repr {
489 MultiValuesRepr::Unset(_) => 0,
490 $($(#[$cfg])* MultiValuesRepr::$variant(values) => values.len(),)+
491 }
492 };
493}
494
495/// Clears the concrete elements of each collection storage variant.
496macro_rules! multi_values_clear_match {
497 ($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
498 match &mut $value.repr {
499 MultiValuesRepr::Unset(_) => {}
500 $($(#[$cfg])* MultiValuesRepr::$variant(values) => values.clear(),)+
501 }
502 };
503}
504
505/// Appends same-typed elements to an existing collection storage variant.
506macro_rules! multi_values_append_match {
507 ($left:expr, $right:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
508 match (&mut $left.repr, &mut $right.repr) {
509 $(
510 $(#[$cfg])*
511 (MultiValuesRepr::$variant(values), MultiValuesRepr::$variant(other_values)) => {
512 values.append(other_values);
513 }
514 )+
515 (slot @ MultiValuesRepr::Unset(_), other_values) => {
516 *slot = std::mem::replace(other_values, MultiValuesRepr::Unset(DataType::String));
517 }
518 _ => unreachable!(),
519 }
520 };
521}
522
523/// Clones the first collection element into a scalar value.
524macro_rules! multi_values_first_value_match {
525 ($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
526 match &$value.repr {
527 MultiValuesRepr::Unset(data_type) => Value::new_unset(*data_type),
528 $(
529 $(#[$cfg])*
530 MultiValuesRepr::$variant(values) => values
531 .first()
532 .map(|value| materialize_stored!($materialization, value))
533 .map(Value::$variant)
534 .unwrap_or(Value::new_unset($data_type)),
535 )+
536 }
537 };
538}
539
540/// Moves the first collection element into a scalar value.
541macro_rules! multi_values_into_first_value_match {
542 ($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
543 match $value.repr {
544 MultiValuesRepr::Unset(data_type) => Value::new_unset(data_type),
545 $(
546 $(#[$cfg])*
547 MultiValuesRepr::$variant(values) => values
548 .into_iter()
549 .next()
550 .map(Value::$variant)
551 .unwrap_or(Value::new_unset($data_type)),
552 )+
553 }
554 };
555}
556
557/// Merges same-typed collection storage while preserving element order.
558macro_rules! multi_values_merge_match {
559 ($left:expr, $right:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
560 match (&mut $left.repr, &$right.repr) {
561 $(
562 $(#[$cfg])*
563 (MultiValuesRepr::$variant(values), MultiValuesRepr::$variant(other_values)) => {
564 values.extend_from_slice(other_values)
565 }
566 )+
567 (slot @ MultiValuesRepr::Unset(_), other_values) => *slot = other_values.clone(),
568 _ => unreachable!(),
569 }
570 };
571}
572
573/// Converts one private scalar storage variant into collection storage.
574macro_rules! value_into_multi_values_match {
575 ($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
576 match $value.repr {
577 ValueRepr::Unset(data_type) => MultiValues::new_unset(data_type),
578 $($(#[$cfg])* ValueRepr::$variant(value) => {
579 MultiValues::$variant(vec![value_storage_into_multi!($variant, value)])
580 },)+
581 }
582 };
583}
584
585impl MultiValues {
586 /// Generic constructor method
587 ///
588 /// Creates `MultiValues` from any supported input form, avoiding direct
589 /// use of enum variants at call sites.
590 ///
591 /// Supported input forms include single values, vectors, slices, arrays,
592 /// borrowed vectors, and borrowed string collections for supported element
593 /// types.
594 ///
595 /// # Type Parameters
596 ///
597 /// * `S` - Input type convertible into [`MultiValues`].
598 ///
599 /// # Parameters
600 ///
601 /// * `values` - Values to convert into a collection.
602 ///
603 /// # Returns
604 ///
605 /// Returns `MultiValues` wrapping the converted input values.
606 ///
607 /// # Examples
608 ///
609 /// ```rust
610 /// use qubit_value::MultiValues;
611 ///
612 /// // Basic types
613 /// let mv = MultiValues::new(vec![1, 2, 3]);
614 /// assert_eq!(mv.len(), 3);
615 ///
616 /// // Strings
617 /// let mv = MultiValues::new(vec!["a".to_string(), "b".to_string()]);
618 /// assert_eq!(mv.len(), 2);
619 /// ```
620 #[inline(always)]
621 pub fn new<S>(values: S) -> Self
622 where
623 S: Into<Self>,
624 {
625 values.into()
626 }
627
628 /// Generic getter method for multiple values.
629 ///
630 /// Performs a strict typed read of all stored values as `Vec<T>`.
631 ///
632 /// # Type Parameters
633 ///
634 /// * `T` - The target element type to retrieve.
635 ///
636 /// # Returns
637 ///
638 /// Returns the list of values when the stored type matches `T`.
639 ///
640 /// # Errors
641 ///
642 /// Returns [`ValueError::Missing`] when the container is unset with the
643 /// requested type, or [`ValueError::TypeMismatch`] when the stored type
644 /// differs from `T`.
645 ///
646 /// # Examples
647 ///
648 /// ```rust
649 /// use qubit_value::MultiValues;
650 ///
651 /// let multi = MultiValues::Int32(vec![1, 2, 3]);
652 ///
653 /// // Through type inference
654 /// let nums: Vec<i32> = multi.get().unwrap();
655 /// assert_eq!(nums, vec![1, 2, 3]);
656 ///
657 /// // Explicitly specify type parameter
658 /// let nums = multi.get::<i32>().unwrap();
659 /// assert_eq!(nums, vec![1, 2, 3]);
660 /// ```
661 #[must_use = "the strict collection read result should be handled"]
662 #[inline(always)]
663 pub fn get<T>(&self) -> ValueResult<Vec<T>>
664 where
665 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
666 {
667 Vec::<T>::try_from(self)
668 }
669
670 /// Generic getter method with a default value list.
671 ///
672 /// Returns the supplied default only when this container is unset. A
673 /// concrete empty vector remains an empty result.
674 ///
675 /// # Type Parameters
676 ///
677 /// * `T` - Target element type for the strict read.
678 ///
679 /// # Parameters
680 ///
681 /// * `default` - Lazily materialized list used only for unset storage.
682 ///
683 /// # Returns
684 ///
685 /// The concrete stored list, or `default` for unset storage.
686 ///
687 /// # Errors
688 ///
689 /// Returns [`ValueError::TypeMismatch`] when the stored type differs from
690 /// `T`.
691 #[must_use = "the strict collection read result should be handled"]
692 #[inline(always)]
693 pub fn get_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
694 where
695 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
696 {
697 match self.get() {
698 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => {
699 Ok(default.into_value_default())
700 }
701 result => result,
702 }
703 }
704
705 /// Strictly reads all values or calls `default` only when storage is unset.
706 ///
707 /// A concrete empty collection is returned unchanged and type mismatches
708 /// are preserved without invoking the callback.
709 ///
710 /// # Type Parameters
711 ///
712 /// * `T` - Target element type.
713 /// * `F` - Deferred fallback producing the complete list.
714 ///
715 /// # Parameters
716 ///
717 /// * `default` - Callback invoked only for unset storage.
718 ///
719 /// # Returns
720 ///
721 /// The stored list or the callback result.
722 ///
723 /// # Errors
724 ///
725 /// Returns [`ValueError::TypeMismatch`] for an incompatible concrete
726 /// collection without invoking the callback.
727 #[must_use = "the strict collection read result should be handled"]
728 #[inline(always)]
729 pub fn get_or_else<T, F>(&self, default: F) -> ValueResult<Vec<T>>
730 where
731 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
732 F: FnOnce() -> Vec<T>,
733 {
734 match self.get() {
735 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => Ok(default()),
736 result => result,
737 }
738 }
739
740 /// Generic getter method for the first value
741 ///
742 /// Reads the first stored value as `T`, performing strict type checking.
743 ///
744 /// `get_first<T>()` does not do cross-type conversion. When the `converter`
745 /// feature is enabled, use `to<T>()` for compatible cross-type conversion.
746 ///
747 /// # Type Parameters
748 ///
749 /// * `T` - The target element type to retrieve.
750 ///
751 /// # Returns
752 ///
753 /// Returns the first value when the stored type matches `T` and at least
754 /// one value exists.
755 ///
756 /// # Errors
757 ///
758 /// Returns [`ValueError::Missing`] when the requested type matches but no
759 /// value is stored, or [`ValueError::TypeMismatch`] when the stored type
760 /// differs from `T`.
761 ///
762 /// # Examples
763 ///
764 /// ```rust
765 /// use qubit_value::MultiValues;
766 ///
767 /// let multi = MultiValues::Int32(vec![42, 100, 200]);
768 ///
769 /// // Through type inference
770 /// let first: i32 = multi.get_first().unwrap();
771 /// assert_eq!(first, 42);
772 ///
773 /// // Explicitly specify type parameter
774 /// let first = multi.get_first::<i32>().unwrap();
775 /// assert_eq!(first, 42);
776 ///
777 /// // String type
778 /// let multi = MultiValues::String(vec!["hello".to_string(), "world".to_string()]);
779 /// let first: String = multi.get_first().unwrap();
780 /// assert_eq!(first, "hello");
781 /// ```
782 #[must_use = "the strict first-value result should be handled"]
783 #[inline(always)]
784 pub fn get_first<T>(&self) -> ValueResult<T>
785 where
786 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
787 {
788 T::try_from(self)
789 }
790
791 /// Generic first-value getter with a default value.
792 ///
793 /// Returns the supplied default only when the container is unset. A
794 /// concrete empty vector returns [`ValueError::Missing`]; type mismatches
795 /// are also preserved.
796 ///
797 /// # Type Parameters
798 ///
799 /// * `T` - Target type for the strict first-item read.
800 ///
801 /// # Parameters
802 ///
803 /// * `default` - Lazily materialized value used only for unset storage.
804 ///
805 /// # Returns
806 ///
807 /// The first concrete item, or `default` for unset storage.
808 ///
809 /// # Errors
810 ///
811 /// Returns [`ValueError::Missing`] for a concrete empty collection or
812 /// [`ValueError::TypeMismatch`] when the stored type differs from `T`.
813 #[must_use = "the strict first-value result should be handled"]
814 #[inline(always)]
815 pub fn get_first_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
816 where
817 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
818 {
819 match self.get_first() {
820 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => {
821 Ok(default.into_value_default())
822 }
823 result => result,
824 }
825 }
826
827 /// Strictly reads the first value or calls `default` only when unset.
828 ///
829 /// # Type Parameters
830 ///
831 /// * `T` - Target element type.
832 /// * `F` - Deferred fallback producing one element.
833 ///
834 /// # Parameters
835 ///
836 /// * `default` - Callback invoked only for unset storage.
837 ///
838 /// # Returns
839 ///
840 /// The first stored item or the callback result.
841 ///
842 /// # Errors
843 ///
844 /// Preserves empty-collection and type-mismatch errors without invoking
845 /// the callback.
846 #[must_use = "the strict first-value result should be handled"]
847 #[inline(always)]
848 pub fn get_first_or_else<T, F>(&self, default: F) -> ValueResult<T>
849 where
850 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
851 F: FnOnce() -> T,
852 {
853 match self.get_first() {
854 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => Ok(default()),
855 result => result,
856 }
857 }
858
859 /// Generic setter method
860 ///
861 /// Replaces the entire list with the converted input values.
862 ///
863 /// This operation updates the stored type to the input element type and
864 /// does not validate runtime compatibility with the previous variant.
865 ///
866 /// Supports any input that can be converted into [`MultiValues`], including
867 /// single values, vectors, slices, arrays, and borrowed vectors for
868 /// supported element types.
869 ///
870 /// Existing values are replaced, and the stored type becomes the converted
871 /// input type.
872 ///
873 /// # Type Parameters
874 ///
875 /// * `S` - Input type convertible into [`MultiValues`].
876 ///
877 /// # Parameters
878 ///
879 /// * `values` - The values to set.
880 ///
881 /// # Compile-time restriction
882 ///
883 /// Unsupported input types fail to compile because they do not implement
884 /// `Into<MultiValues>`.
885 ///
886 /// # Examples
887 ///
888 /// ```rust
889 /// use qubit_datatype::DataType;
890 /// use qubit_value::MultiValues;
891 ///
892 /// // 1) Vec<T>
893 /// let mut mv = MultiValues::Unset(DataType::Int32);
894 /// mv.set(vec![42, 100, 200]);
895 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200]);
896 ///
897 /// // 2) &[T]
898 /// let mut mv = MultiValues::Unset(DataType::Int32);
899 /// let slice = &[7, 8, 9][..];
900 /// mv.set(slice);
901 /// assert_eq!(mv.get_int32s().unwrap(), &[7, 8, 9]);
902 ///
903 /// // 3) Single T
904 /// let mut mv = MultiValues::Unset(DataType::Int32);
905 /// mv.set(42);
906 /// assert_eq!(mv.get_int32s().unwrap(), &[42]);
907 ///
908 /// // String example
909 /// let mut mv = MultiValues::Unset(DataType::String);
910 /// mv.set(vec!["hello".to_string(), "world".to_string()]);
911 /// assert_eq!(mv.get_strings().unwrap(), &["hello", "world"]);
912 /// ```
913 #[inline(always)]
914 pub fn set<S>(&mut self, values: S)
915 where
916 S: Into<Self>,
917 {
918 *self = values.into();
919 }
920
921 /// Generic add method
922 ///
923 /// Appends converted input values to the existing list with strict type
924 /// checking.
925 ///
926 /// Supports any input that can be converted into [`MultiValues`], including
927 /// single values, vectors, slices, arrays, and borrowed vectors for
928 /// supported element types.
929 ///
930 /// The converted input must have the same data type as the current
931 /// container. An empty container keeps its declared type until
932 /// non-empty values of the same type are appended.
933 ///
934 /// # Type Parameters
935 ///
936 /// * `S` - Input type convertible into [`MultiValues`].
937 ///
938 /// # Parameters
939 ///
940 /// * `values` - Values to append.
941 ///
942 /// # Returns
943 ///
944 /// `Ok(())` after appending, including when the input is empty.
945 ///
946 /// # Errors
947 ///
948 /// Returns [`ValueError::TypeMismatch`] when the converted input data type
949 /// differs from the current container data type.
950 ///
951 /// # Examples
952 ///
953 /// ```rust
954 /// use qubit_datatype::DataType;
955 /// use qubit_value::MultiValues;
956 ///
957 /// // 1) Single T
958 /// let mut mv = MultiValues::Int32(vec![42]);
959 /// mv.add(100).unwrap();
960 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100]);
961 ///
962 /// // 2) Vec<T>
963 /// mv.add(vec![200, 300]).unwrap();
964 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300]);
965 ///
966 /// // 3) &[T]
967 /// let slice = &[400, 500][..];
968 /// mv.add(slice).unwrap();
969 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300, 400, 500]);
970 /// ```
971 pub fn add<S>(&mut self, values: S) -> ValueResult<()>
972 where
973 S: Into<Self>,
974 {
975 let mut other = values.into();
976 if self.data_type() != other.data_type() {
977 return Err(ValueError::TypeMismatch {
978 expected: self.data_type(),
979 actual: other.data_type(),
980 });
981 }
982 if other.is_empty() {
983 return Ok(());
984 }
985
986 for_each_value_type!(multi_values_append_match, self, other);
987
988 Ok(())
989 }
990
991 /// Get the data type of the values
992 ///
993 /// # Returns
994 ///
995 /// Returns the data type corresponding to these multiple values
996 ///
997 /// # Examples
998 ///
999 /// ```rust
1000 /// use qubit_datatype::DataType;
1001 /// use qubit_value::MultiValues;
1002 ///
1003 /// let values = MultiValues::Int32(vec![1, 2, 3]);
1004 /// assert_eq!(values.data_type(), DataType::Int32);
1005 /// ```
1006 #[must_use = "the collection element type should be used"]
1007 #[inline(always)]
1008 pub fn data_type(&self) -> DataType {
1009 for_each_value_type!(multi_values_data_type_match, self)
1010 }
1011
1012 /// Returns the number of values.
1013 ///
1014 /// # Returns
1015 ///
1016 /// The number of values contained in these multiple values. An unset
1017 /// collection has length zero.
1018 ///
1019 /// # Examples
1020 ///
1021 /// ```rust
1022 /// use qubit_datatype::DataType;
1023 /// use qubit_value::MultiValues;
1024 ///
1025 /// let values = MultiValues::Int32(vec![1, 2, 3]);
1026 /// assert_eq!(values.len(), 3);
1027 ///
1028 /// let empty = MultiValues::Unset(DataType::String);
1029 /// assert_eq!(empty.len(), 0);
1030 /// ```
1031 #[inline(always)]
1032 #[must_use]
1033 pub fn len(&self) -> usize {
1034 for_each_value_type!(multi_values_count_match, self)
1035 }
1036
1037 /// Tests whether this collection contains no values.
1038 ///
1039 /// An unset collection and a concrete empty vector both have length zero.
1040 /// Use [`MultiValues::is_unset`] when the distinction between no collection
1041 /// and a concrete empty collection matters.
1042 ///
1043 /// # Returns
1044 ///
1045 /// `true` when [`Self::len`] is zero; otherwise, `false`.
1046 #[inline(always)]
1047 #[must_use]
1048 pub fn is_empty(&self) -> bool {
1049 self.len() == 0
1050 }
1051
1052 /// Tests whether this container has no concrete vector.
1053 ///
1054 /// # Returns
1055 ///
1056 /// Returns `true` only for [`MultiValues::Unset`]. A concrete empty vector
1057 /// returns `false`.
1058 ///
1059 /// # Examples
1060 ///
1061 /// ```rust
1062 /// use qubit_datatype::DataType;
1063 /// use qubit_value::MultiValues;
1064 ///
1065 /// let values = MultiValues::Int32(vec![]);
1066 /// assert!(!values.is_unset());
1067 ///
1068 /// let empty = MultiValues::Unset(DataType::String);
1069 /// assert!(empty.is_unset());
1070 /// ```
1071 #[inline(always)]
1072 #[must_use]
1073 pub fn is_unset(&self) -> bool {
1074 matches!(self.repr, MultiValuesRepr::Unset(_))
1075 }
1076
1077 /// Tests whether a concrete collection belongs to the numeric type family.
1078 ///
1079 /// A concrete empty numeric vector returns `true`; an unset collection
1080 /// returns `false`, even when its declared type is numeric.
1081 ///
1082 /// # Returns
1083 ///
1084 /// `true` for concrete collections with a numeric element type.
1085 #[inline(always)]
1086 #[must_use]
1087 pub fn is_numeric(&self) -> bool {
1088 !self.is_unset() && self.data_type().is_numeric()
1089 }
1090
1091 /// Removes the concrete vector while preserving its declared data type.
1092 #[inline(always)]
1093 pub fn unset(&mut self) {
1094 *self = MultiValues::new_unset(self.data_type());
1095 }
1096
1097 /// Clears all values while preserving a concrete collection and its type.
1098 /// An unset collection remains unset because it has no concrete vector to
1099 /// clear.
1100 ///
1101 /// # Examples
1102 ///
1103 /// ```rust
1104 /// use qubit_datatype::DataType;
1105 /// use qubit_value::MultiValues;
1106 ///
1107 /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
1108 /// values.clear();
1109 /// assert_eq!(values.len(), 0);
1110 /// assert_eq!(values.data_type(), DataType::Int32);
1111 /// ```
1112 #[inline(always)]
1113 pub fn clear(&mut self) {
1114 for_each_value_type!(multi_values_clear_match, self)
1115 }
1116
1117 /// Set the data type
1118 ///
1119 /// If the new type differs from the current type, clears all values and
1120 /// sets the new type.
1121 ///
1122 /// # Parameters
1123 ///
1124 /// * `data_type` - The data type to set
1125 ///
1126 /// # Examples
1127 ///
1128 /// ```rust
1129 /// use qubit_datatype::DataType;
1130 /// use qubit_value::MultiValues;
1131 ///
1132 /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
1133 /// values.set_type(DataType::String);
1134 /// assert!(values.is_unset());
1135 /// assert_eq!(values.data_type(), DataType::String);
1136 /// ```
1137 #[inline(always)]
1138 pub fn set_type(&mut self, data_type: DataType) {
1139 if self.data_type() != data_type {
1140 *self = MultiValues::new_unset(data_type);
1141 }
1142 }
1143
1144 /// Converts the first element to a single [`Value`].
1145 ///
1146 /// Returns `Value::Unset` with the same declared type when no element is
1147 /// stored.
1148 ///
1149 /// # Returns
1150 ///
1151 /// A cloned first item, or a typed unset value when no item exists.
1152 #[must_use = "the projected first value should be used"]
1153 #[inline(always)]
1154 pub fn first_value(&self) -> Value {
1155 for_each_value_type!(multi_values_first_value_match, self)
1156 }
1157
1158 /// Consumes this collection and returns its first item as a [`Value`].
1159 ///
1160 /// Empty and unset collections become [`Value::Unset`] with the same data
1161 /// type. Owned element storage is moved instead of cloned.
1162 ///
1163 /// # Returns
1164 ///
1165 /// The owned first item, or a typed unset value when no item exists.
1166 pub fn into_first_value(self) -> Value {
1167 for_each_value_type!(multi_values_into_first_value_match, self)
1168 }
1169
1170 /// Appends all values from another container with the same data type.
1171 ///
1172 /// # Parameters
1173 ///
1174 /// * `other` - Collection whose values are cloned and appended.
1175 ///
1176 /// # Returns
1177 ///
1178 /// `Ok(())` after appending, including when `other` is empty.
1179 ///
1180 /// # Errors
1181 ///
1182 /// Returns [`ValueError::TypeMismatch`] when `other` has a different data
1183 /// type.
1184 pub fn merge(&mut self, other: &MultiValues) -> ValueResult<()> {
1185 if self.data_type() != other.data_type() {
1186 return Err(ValueError::TypeMismatch {
1187 expected: self.data_type(),
1188 actual: other.data_type(),
1189 });
1190 }
1191 if other.is_empty() {
1192 return Ok(());
1193 }
1194 for_each_value_type!(multi_values_merge_match, self, other);
1195 Ok(())
1196 }
1197}
1198
1199impl From<Value> for MultiValues {
1200 fn from(value: Value) -> Self {
1201 for_each_value_type!(value_into_multi_values_match, value)
1202 }
1203}
1204
1205/// Converts the first collection element with a standalone policy and limits.
1206#[cfg(feature = "converter")]
1207macro_rules! multi_values_convert_first_match {
1208 ($value:expr, $policy:expr, $limits:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
1209 match &$value.repr {
1210 MultiValuesRepr::Unset(from) => {
1211 Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
1212 }
1213 $(
1214 $(#[$cfg])*
1215 MultiValuesRepr::$variant(values) => {
1216 convert_first_with(DataConverters::from(values), $policy, $limits)
1217 }
1218 )+
1219 }
1220 };
1221}
1222
1223/// Converts every collection element with a standalone policy and limits.
1224#[cfg(feature = "converter")]
1225macro_rules! multi_values_convert_list_match {
1226 ($value:expr, $policy:expr, $limits:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
1227 match &$value.repr {
1228 MultiValuesRepr::Unset(from) => {
1229 Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
1230 }
1231 $(
1232 $(#[$cfg])*
1233 MultiValuesRepr::$variant(values) => {
1234 convert_values_with(DataConverters::from(values), $policy, $limits)
1235 }
1236 )+
1237 }
1238 };
1239}
1240
1241/// Converts the first collection element through a caller-owned session.
1242#[cfg(feature = "converter")]
1243macro_rules! multi_values_convert_first_in_match {
1244 ($value:expr, $session:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
1245 match &$value.repr {
1246 MultiValuesRepr::Unset(from) => {
1247 Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
1248 }
1249 $(
1250 $(#[$cfg])*
1251 MultiValuesRepr::$variant(values) => {
1252 DataConverters::from(values)
1253 .to_first_in($session)
1254 .map_err(ValueError::from)
1255 }
1256 )+
1257 }
1258 };
1259}
1260
1261/// Converts every collection element through a caller-owned session.
1262#[cfg(feature = "converter")]
1263macro_rules! multi_values_convert_list_in_match {
1264 ($value:expr, $session:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
1265 match &$value.repr {
1266 MultiValuesRepr::Unset(from) => {
1267 Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
1268 }
1269 $(
1270 $(#[$cfg])*
1271 MultiValuesRepr::$variant(values) => {
1272 DataConverters::from(values)
1273 .to_vec_in($session)
1274 .map_err(ValueError::from)
1275 }
1276 )+
1277 }
1278 };
1279}
1280
1281// ============================================================================
1282// Inherent conversion APIs
1283// ============================================================================
1284
1285/// Converts the first item from a batch converter using conversion policy and
1286/// limits.
1287///
1288/// # Type Parameters
1289///
1290/// * `T` - Target type.
1291/// * `I` - Iterator type wrapped by `DataConverters`.
1292///
1293/// # Parameters
1294///
1295/// * `values` - Batch converter containing source values.
1296/// * `policy` - Conversion policy forwarded to `qubit_datatype`.
1297/// * `limits` - Conversion limits forwarded to `qubit_datatype`.
1298///
1299/// # Returns
1300///
1301/// Returns the converted first value.
1302///
1303/// # Errors
1304///
1305/// Returns the mapped single-value conversion error for an empty source or an
1306/// invalid first source value.
1307#[inline(always)]
1308#[cfg(feature = "converter")]
1309fn convert_first_with<'a, T, I>(
1310 values: DataConverters<I>,
1311 policy: &ConversionPolicy,
1312 limits: &ConversionLimits,
1313) -> ValueResult<T>
1314where
1315 T: DataConversionTarget,
1316 I: Iterator,
1317 I::Item: Into<DataConverter<'a>>,
1318{
1319 values.to_first_with(policy, limits).map_err(ValueError::from)
1320}
1321
1322/// Converts every item from a batch converter using conversion policy and
1323/// limits.
1324///
1325/// # Type Parameters
1326///
1327/// * `T` - Target element type.
1328/// * `I` - Iterator type wrapped by `DataConverters`.
1329///
1330/// # Parameters
1331///
1332/// * `values` - Batch converter containing source values.
1333/// * `policy` - Conversion policy forwarded to `qubit_datatype`.
1334/// * `limits` - Conversion limits forwarded to `qubit_datatype`.
1335///
1336/// # Returns
1337///
1338/// Returns converted values in the original order.
1339///
1340/// # Errors
1341///
1342/// Returns a mapped batch conversion error containing the failing source index.
1343#[inline(always)]
1344#[cfg(feature = "converter")]
1345fn convert_values_with<'a, T, I>(
1346 values: DataConverters<I>,
1347 policy: &ConversionPolicy,
1348 limits: &ConversionLimits,
1349) -> ValueResult<Vec<T>>
1350where
1351 T: DataConversionTarget,
1352 I: Iterator,
1353 I::Item: Into<DataConverter<'a>>,
1354{
1355 values.to_vec_with(policy, limits).map_err(ValueError::from)
1356}
1357
1358#[cfg(feature = "converter")]
1359impl MultiValues {
1360 /// Enriches only missing failures after conversion, retaining
1361 /// resource-error priority.
1362 fn contextual_conversion_error(&self, error: ValueError, first: bool) -> ValueError {
1363 let ValueError::Missing(missing) = error else {
1364 return error;
1365 };
1366 let reason = if self.is_unset() {
1367 crate::ValueMissingReason::UnsetCollection
1368 } else if self.is_empty() {
1369 crate::ValueMissingReason::EmptyCollection
1370 } else {
1371 crate::ValueMissingReason::Conversion
1372 };
1373 let missing = missing.with_storage(self.data_type(), reason);
1374 ValueError::Missing(if first { missing.with_first_index() } else { missing })
1375 }
1376
1377 /// Converts the first stored value to `T`.
1378 ///
1379 /// Unlike [`Self::get_first`], this method uses shared `DataConverter`
1380 /// conversion rules instead of strict type matching. For example, a stored
1381 /// `String("1")` can be converted to `bool`.
1382 ///
1383 /// # Type Parameters
1384 ///
1385 /// * `T` - Target type.
1386 ///
1387 /// # Returns
1388 ///
1389 /// The converted first value.
1390 ///
1391 /// # Errors
1392 ///
1393 /// Returns a structured missing-value conversion error when the container
1394 /// is unset, an empty-collection error for a concrete empty vector, or a
1395 /// conversion error when the first value cannot be converted to `T`.
1396 #[inline(always)]
1397 pub fn to_first<T>(&self) -> ValueResult<T>
1398 where
1399 T: DataConversionTarget,
1400 {
1401 self.to_first_with(ConversionPolicy::default_ref(), ConversionLimits::default_ref())
1402 }
1403
1404 /// Converts the first stored value to `T`, or returns `default` when the
1405 /// container is unset or conversion reports a missing value.
1406 ///
1407 /// An unset collection can use the default. A concrete empty collection
1408 /// and a policy-missing collection item (including the first item) remain
1409 /// errors and do not use the default; ordinary conversion errors are also
1410 /// preserved.
1411 ///
1412 /// # Type Parameters
1413 ///
1414 /// * `T` - Target type.
1415 ///
1416 /// # Parameters
1417 ///
1418 /// * `default` - Value returned for unset storage or a policy-missing
1419 /// scalar; collection-item and ordinary conversion errors are returned.
1420 ///
1421 /// # Returns
1422 ///
1423 /// The converted first value, or `default` for unset or conversion-missing
1424 /// storage.
1425 ///
1426 /// # Errors
1427 ///
1428 /// Returns an empty-collection error for a concrete empty vector, or a
1429 /// conversion error when the first value cannot be converted to `T`.
1430 #[inline]
1431 pub fn to_first_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
1432 where
1433 T: DataConversionTarget,
1434 {
1435 match self.to_first() {
1436 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
1437 Ok(default.into_value_default())
1438 }
1439 result => result,
1440 }
1441 }
1442
1443 /// Converts the first value or calls `default` when storage is unset or
1444 /// conversion reports a missing value.
1445 ///
1446 /// # Type Parameters
1447 ///
1448 /// * `T` - Target conversion type.
1449 /// * `F` - Deferred fallback producing `T`.
1450 ///
1451 /// # Parameters
1452 ///
1453 /// * `default` - Callback invoked for unset storage or a policy-missing
1454 /// scalar; it is not invoked for a missing collection item or ordinary
1455 /// conversion error.
1456 ///
1457 /// # Returns
1458 ///
1459 /// The converted first item or the callback result.
1460 ///
1461 /// # Errors
1462 ///
1463 /// Preserves empty-collection, policy-missing-item, and ordinary
1464 /// concrete-value conversion errors without invoking the callback.
1465 #[inline]
1466 pub fn to_first_or_else<T, F>(&self, default: F) -> ValueResult<T>
1467 where
1468 T: DataConversionTarget,
1469 F: FnOnce() -> T,
1470 {
1471 match self.to_first() {
1472 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
1473 result => result,
1474 }
1475 }
1476
1477 /// Converts the first stored value to `T` using conversion policy and
1478 /// limits.
1479 ///
1480 /// Stored strings are collection items and are never split again by scalar
1481 /// string collection policy.
1482 ///
1483 /// # Type Parameters
1484 ///
1485 /// * `T` - Target type.
1486 ///
1487 /// # Parameters
1488 ///
1489 /// * `policy` - Conversion policy forwarded to `qubit_datatype`.
1490 /// * `limits` - Conversion limits forwarded to `qubit_datatype`.
1491 ///
1492 /// # Returns
1493 ///
1494 /// The converted first value.
1495 ///
1496 /// # Errors
1497 ///
1498 /// Returns a structured missing-value conversion error when the container
1499 /// is unset, an empty-collection error for a concrete empty vector, or a
1500 /// conversion error when the first value cannot be converted to `T`.
1501 pub fn to_first_with<T>(&self, policy: &ConversionPolicy, limits: &ConversionLimits) -> ValueResult<T>
1502 where
1503 T: DataConversionTarget,
1504 {
1505 for_each_value_type!(multi_values_convert_first_match, self, policy, limits)
1506 .map_err(|error| self.contextual_conversion_error(error, true))
1507 }
1508
1509 /// Converts the first stored value using an existing conversion session.
1510 ///
1511 /// # Type Parameters
1512 ///
1513 /// * `T` - Target element type supported by the shared conversion layer.
1514 ///
1515 /// # Parameters
1516 ///
1517 /// * `session` - Caller-owned session providing policy, limits, and budget.
1518 ///
1519 /// # Returns
1520 ///
1521 /// The converted first element.
1522 ///
1523 /// # Errors
1524 ///
1525 /// Returns a structured missing, conversion, or budget error when the
1526 /// first element cannot be produced as `T`.
1527 pub fn to_first_in<T>(&self, session: &mut ConversionSession<'_>) -> ValueResult<T>
1528 where
1529 T: DataConversionTarget,
1530 {
1531 for_each_value_type!(multi_values_convert_first_in_match, self, session)
1532 .map_err(|error| self.contextual_conversion_error(error, true))
1533 }
1534
1535 /// Converts the first stored value to `T` using conversion policy and
1536 /// limits, or returns `default` when storage is unset or conversion
1537 /// reports a missing value.
1538 ///
1539 /// # Type Parameters
1540 ///
1541 /// * `T` - Target conversion type.
1542 ///
1543 /// # Parameters
1544 ///
1545 /// * `default` - Lazily materialized value used for unset storage or a
1546 /// conversion-missing result.
1547 /// * `policy` - Conversion policy forwarded to `qubit_datatype`.
1548 /// * `limits` - Conversion limits forwarded to `qubit_datatype`.
1549 ///
1550 /// # Returns
1551 ///
1552 /// The converted first item, or `default` for an unset collection or a
1553 /// policy-missing scalar. A missing collection item, including index zero,
1554 /// never uses the default.
1555 ///
1556 /// # Errors
1557 ///
1558 /// Returns an empty-collection error, a missing collection-item error, or
1559 /// an ordinary conversion error for concrete values that cannot be
1560 /// converted under the provided policy and limits. None invokes the
1561 /// fallback.
1562 #[inline]
1563 pub fn to_first_or_with<T>(
1564 &self,
1565 default: impl IntoValueDefault<T>,
1566 policy: &ConversionPolicy,
1567 limits: &ConversionLimits,
1568 ) -> ValueResult<T>
1569 where
1570 T: DataConversionTarget,
1571 {
1572 match self.to_first_with(policy, limits) {
1573 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
1574 Ok(default.into_value_default())
1575 }
1576 result => result,
1577 }
1578 }
1579
1580 /// Converts the first value with the provided policy and limits, or calls
1581 /// `default` when storage is unset or conversion reports a missing
1582 /// value.
1583 ///
1584 /// # Type Parameters
1585 ///
1586 /// * `T` - Target conversion type.
1587 /// * `F` - Deferred fallback producing `T`.
1588 ///
1589 /// # Parameters
1590 ///
1591 /// * `default` - Callback invoked for unset storage or a conversion-missing
1592 /// result.
1593 /// * `policy` - Conversion policy forwarded to the shared converter.
1594 /// * `limits` - Conversion limits forwarded to the shared converter.
1595 ///
1596 /// # Returns
1597 ///
1598 /// The converted first item or the callback result.
1599 ///
1600 /// # Errors
1601 ///
1602 /// Preserves concrete-value conversion errors, including policy-missing
1603 /// collection items, without invoking the callback.
1604 #[inline]
1605 pub fn to_first_or_else_with<T, F>(
1606 &self,
1607 default: F,
1608 policy: &ConversionPolicy,
1609 limits: &ConversionLimits,
1610 ) -> ValueResult<T>
1611 where
1612 T: DataConversionTarget,
1613 F: FnOnce() -> T,
1614 {
1615 match self.to_first_with(policy, limits) {
1616 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
1617 result => result,
1618 }
1619 }
1620
1621 /// Converts all stored values to `T`.
1622 ///
1623 /// Unlike [`Self::get`], this method uses shared `DataConverter` conversion
1624 /// rules for every element instead of strict type matching. A concrete
1625 /// empty vector returns an empty vector; an unset container reports a
1626 /// missing-value conversion error.
1627 ///
1628 /// # Type Parameters
1629 ///
1630 /// * `T` - Target element type.
1631 ///
1632 /// # Returns
1633 ///
1634 /// A vector containing all converted values in the original order.
1635 ///
1636 /// # Errors
1637 ///
1638 /// Returns the first conversion error encountered while converting an
1639 /// element.
1640 pub fn to_list<T>(&self) -> ValueResult<Vec<T>>
1641 where
1642 T: DataConversionTarget,
1643 {
1644 self.to_list_with(ConversionPolicy::default_ref(), ConversionLimits::default_ref())
1645 }
1646
1647 /// Converts all stored values to `T`, or returns `default` when storage is
1648 /// unset or conversion reports a missing value.
1649 ///
1650 /// # Type Parameters
1651 ///
1652 /// * `T` - Target element type.
1653 ///
1654 /// # Parameters
1655 ///
1656 /// * `default` - Lazily materialized list used for unset storage or a
1657 /// policy-missing scalar; collection-item and ordinary conversion errors
1658 /// are returned.
1659 ///
1660 /// # Returns
1661 ///
1662 /// All converted items, or `default` for an unset collection or a
1663 /// policy-missing outer scalar. A policy-missing collection item and an
1664 /// ordinary conversion error never use the default.
1665 ///
1666 /// # Errors
1667 ///
1668 /// Returns the first item conversion error for concrete storage. A
1669 /// policy-missing collection item is preserved and does not use the
1670 /// fallback.
1671 #[inline]
1672 pub fn to_list_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
1673 where
1674 T: DataConversionTarget,
1675 {
1676 match self.to_list() {
1677 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
1678 Ok(default.into_value_default())
1679 }
1680 result => result,
1681 }
1682 }
1683
1684 /// Converts all values or calls `default` when storage is unset or
1685 /// conversion reports a missing value.
1686 ///
1687 /// # Type Parameters
1688 ///
1689 /// * `T` - Target element conversion type.
1690 /// * `F` - Deferred fallback producing the complete list.
1691 ///
1692 /// # Parameters
1693 ///
1694 /// * `default` - Callback invoked for unset storage or a policy-missing
1695 /// scalar; it is not invoked for a missing collection item or ordinary
1696 /// conversion error.
1697 ///
1698 /// # Returns
1699 ///
1700 /// The converted list or the callback result.
1701 ///
1702 /// # Errors
1703 ///
1704 /// Preserves concrete-value conversion errors, including policy-missing
1705 /// collection items, without invoking the callback.
1706 #[inline]
1707 pub fn to_list_or_else<T, F>(&self, default: F) -> ValueResult<Vec<T>>
1708 where
1709 T: DataConversionTarget,
1710 F: FnOnce() -> Vec<T>,
1711 {
1712 match self.to_list() {
1713 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
1714 result => result,
1715 }
1716 }
1717
1718 /// Converts all stored values to `T` using conversion policy and limits.
1719 ///
1720 /// Stored strings are collection items and are never split again by scalar
1721 /// string collection policy.
1722 ///
1723 /// # Type Parameters
1724 ///
1725 /// * `T` - Target element type.
1726 ///
1727 /// # Parameters
1728 ///
1729 /// * `policy` - Conversion policy forwarded to `qubit_datatype`.
1730 /// * `limits` - Conversion limits forwarded to `qubit_datatype`.
1731 ///
1732 /// # Returns
1733 ///
1734 /// A vector containing all converted values in the original order.
1735 ///
1736 /// # Errors
1737 ///
1738 /// Returns the first conversion error encountered while converting an
1739 /// element.
1740 pub fn to_list_with<T>(&self, policy: &ConversionPolicy, limits: &ConversionLimits) -> ValueResult<Vec<T>>
1741 where
1742 T: DataConversionTarget,
1743 {
1744 for_each_value_type!(multi_values_convert_list_match, self, policy, limits)
1745 .map_err(|error| self.contextual_conversion_error(error, false))
1746 }
1747
1748 /// Converts every stored value using an existing conversion session.
1749 ///
1750 /// # Type Parameters
1751 ///
1752 /// * `T` - Target element type supported by the shared conversion layer.
1753 ///
1754 /// # Parameters
1755 ///
1756 /// * `session` - Caller-owned session providing policy, limits, and budget.
1757 ///
1758 /// # Returns
1759 ///
1760 /// Converted elements in their original order.
1761 ///
1762 /// # Errors
1763 ///
1764 /// Returns the first structured missing, conversion, or budget error.
1765 pub fn to_list_in<T>(&self, session: &mut ConversionSession<'_>) -> ValueResult<Vec<T>>
1766 where
1767 T: DataConversionTarget,
1768 {
1769 for_each_value_type!(multi_values_convert_list_in_match, self, session)
1770 .map_err(|error| self.contextual_conversion_error(error, false))
1771 }
1772
1773 /// Converts all stored values to `T` using conversion policy and limits, or
1774 /// returns `default` when storage is unset or conversion reports a
1775 /// missing value.
1776 ///
1777 /// # Type Parameters
1778 ///
1779 /// * `T` - Target element type.
1780 ///
1781 /// # Parameters
1782 ///
1783 /// * `default` - Lazily materialized list used for unset storage or a
1784 /// conversion-missing result.
1785 /// * `policy` - Conversion policy forwarded to `qubit_datatype`.
1786 /// * `limits` - Conversion limits forwarded to `qubit_datatype`.
1787 ///
1788 /// # Returns
1789 ///
1790 /// All converted items, or `default` for an unset collection or a
1791 /// policy-missing scalar. A missing collection item and an ordinary
1792 /// conversion error never use the default.
1793 ///
1794 /// # Errors
1795 ///
1796 /// Returns the first item conversion error for concrete storage. Missing
1797 /// collection items and ordinary conversion errors are preserved.
1798 #[inline]
1799 pub fn to_list_or_with<T>(
1800 &self,
1801 default: impl IntoValueDefault<Vec<T>>,
1802 policy: &ConversionPolicy,
1803 limits: &ConversionLimits,
1804 ) -> ValueResult<Vec<T>>
1805 where
1806 T: DataConversionTarget,
1807 {
1808 match self.to_list_with(policy, limits) {
1809 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
1810 Ok(default.into_value_default())
1811 }
1812 result => result,
1813 }
1814 }
1815
1816 /// Converts all values with the provided policy and limits, or calls
1817 /// `default` when storage is unset or conversion reports a missing
1818 /// value.
1819 ///
1820 /// # Type Parameters
1821 ///
1822 /// * `T` - Target element conversion type.
1823 /// * `F` - Deferred fallback producing the complete list.
1824 ///
1825 /// # Parameters
1826 ///
1827 /// * `default` - Callback invoked for unset storage or a policy-missing
1828 /// scalar; it is not invoked for a missing collection item or ordinary
1829 /// conversion error.
1830 /// * `policy` - Conversion policy forwarded to the shared converter.
1831 /// * `limits` - Conversion limits forwarded to the shared converter.
1832 ///
1833 /// # Returns
1834 ///
1835 /// The converted list or the callback result.
1836 ///
1837 /// # Errors
1838 ///
1839 /// Preserves concrete-value conversion errors, including policy-missing
1840 /// collection items, without invoking the callback.
1841 #[inline]
1842 pub fn to_list_or_else_with<T, F>(
1843 &self,
1844 default: F,
1845 policy: &ConversionPolicy,
1846 limits: &ConversionLimits,
1847 ) -> ValueResult<Vec<T>>
1848 where
1849 T: DataConversionTarget,
1850 F: FnOnce() -> Vec<T>,
1851 {
1852 match self.to_list_with(policy, limits) {
1853 Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
1854 result => result,
1855 }
1856 }
1857}
1858
1859impl MultiValues {
1860 // ========================================================================
1861 // Get first value (as single value access)
1862 // ========================================================================
1863
1864 impl_get_first_value! {
1865 /// Get the first boolean value.
1866 ///
1867 /// # Returns
1868 ///
1869 /// If types match and a value exists, returns the first boolean value; see `# Errors`.
1870 ///
1871 /// # Examples
1872 ///
1873 /// ```rust
1874 /// use qubit_value::MultiValues;
1875 ///
1876 /// let values = MultiValues::Bool(vec![true, false]);
1877 /// assert_eq!(values.get_first_bool().unwrap(), true);
1878 /// ```
1879 copy: get_first_bool, Bool, bool, DataType::Bool
1880 }
1881
1882 impl_get_first_value! {
1883 /// Get the first character value
1884 ///
1885 /// # Returns
1886 ///
1887 /// If types match and a value exists, returns the first character value; see `# Errors`.
1888 copy: get_first_char, Char, char, DataType::Char
1889 }
1890
1891 impl_get_first_value! {
1892 /// Get the first int8 value
1893 ///
1894 /// # Returns
1895 ///
1896 /// If types match and a value exists, returns the first int8 value; see `# Errors`.
1897 copy: get_first_int8, Int8, i8, DataType::Int8
1898 }
1899
1900 impl_get_first_value! {
1901 /// Get the first int16 value
1902 ///
1903 /// # Returns
1904 ///
1905 /// If types match and a value exists, returns the first int16 value; see `# Errors`.
1906 copy: get_first_int16, Int16, i16, DataType::Int16
1907 }
1908
1909 impl_get_first_value! {
1910 /// Get the first int32 value
1911 ///
1912 /// # Returns
1913 ///
1914 /// If types match and a value exists, returns the first int32 value; see `# Errors`.
1915 copy: get_first_int32, Int32, i32, DataType::Int32
1916 }
1917
1918 impl_get_first_value! {
1919 /// Get the first int64 value
1920 ///
1921 /// # Returns
1922 ///
1923 /// If types match and a value exists, returns the first int64 value; see `# Errors`.
1924 copy: get_first_int64, Int64, i64, DataType::Int64
1925 }
1926
1927 impl_get_first_value! {
1928 /// Get the first int128 value
1929 ///
1930 /// # Returns
1931 ///
1932 /// If types match and a value exists, returns the first int128 value; see `# Errors`.
1933 copy: get_first_int128, Int128, i128, DataType::Int128
1934 }
1935
1936 impl_get_first_value! {
1937 /// Get the first uint8 value
1938 ///
1939 /// # Returns
1940 ///
1941 /// If types match and a value exists, returns the first uint8 value; see `# Errors`.
1942 copy: get_first_uint8, UInt8, u8, DataType::UInt8
1943 }
1944
1945 impl_get_first_value! {
1946 /// Get the first uint16 value
1947 ///
1948 /// # Returns
1949 ///
1950 /// If types match and a value exists, returns the first uint16 value; see `# Errors`.
1951 copy: get_first_uint16, UInt16, u16, DataType::UInt16
1952 }
1953
1954 impl_get_first_value! {
1955 /// Get the first uint32 value
1956 ///
1957 /// # Returns
1958 ///
1959 /// If types match and a value exists, returns the first uint32 value; see `# Errors`.
1960 copy: get_first_uint32, UInt32, u32, DataType::UInt32
1961 }
1962
1963 impl_get_first_value! {
1964 /// Get the first uint64 value
1965 ///
1966 /// # Returns
1967 ///
1968 /// If types match and a value exists, returns the first uint64 value; see `# Errors`.
1969 copy: get_first_uint64, UInt64, u64, DataType::UInt64
1970 }
1971
1972 impl_get_first_value! {
1973 /// Get the first uint128 value
1974 ///
1975 /// # Returns
1976 ///
1977 /// If types match and a value exists, returns the first uint128 value; see `# Errors`.
1978 copy: get_first_uint128, UInt128, u128, DataType::UInt128
1979 }
1980
1981 impl_get_first_value! {
1982 /// Get the first float32 value
1983 ///
1984 /// # Returns
1985 ///
1986 /// If types match and a value exists, returns the first float32 value; see `# Errors`.
1987 copy: get_first_float32, Float32, f32, DataType::Float32
1988 }
1989
1990 impl_get_first_value! {
1991 /// Get the first float64 value
1992 ///
1993 /// # Returns
1994 ///
1995 /// If types match and a value exists, returns the first float64 value; see `# Errors`.
1996 copy: get_first_float64, Float64, f64, DataType::Float64
1997 }
1998
1999 impl_get_first_value! {
2000 /// Get the first string reference
2001 ///
2002 /// # Returns
2003 ///
2004 /// If types match and a value exists, returns a reference to the first
2005 /// string; see `# Errors`.
2006 ref: get_first_string, String, &str, DataType::String, |s: &String| s.as_str()
2007 }
2008
2009 impl_get_first_value! {
2010 /// Get the first date value
2011 ///
2012 /// # Returns
2013 ///
2014 /// If types match and a value exists, returns the first date value; see `# Errors`.
2015 #[cfg(feature = "chrono")]
2016 copy: get_first_date, Date, NaiveDate, DataType::Date
2017 }
2018
2019 impl_get_first_value! {
2020 /// Get the first time value
2021 ///
2022 /// # Returns
2023 ///
2024 /// If types match and a value exists, returns the first time value; see `# Errors`.
2025 #[cfg(feature = "chrono")]
2026 copy: get_first_time, Time, NaiveTime, DataType::Time
2027 }
2028
2029 impl_get_first_value! {
2030 /// Get the first datetime value
2031 ///
2032 /// # Returns
2033 ///
2034 /// If types match and a value exists, returns the first datetime value; see `# Errors`.
2035 #[cfg(feature = "chrono")]
2036 copy: get_first_datetime, DateTime, NaiveDateTime, DataType::DateTime
2037 }
2038
2039 impl_get_first_value! {
2040 /// Get the first UTC instant value
2041 ///
2042 /// # Returns
2043 ///
2044 /// If types match and a value exists, returns the first UTC instant
2045 /// value; see `# Errors`.
2046 #[cfg(feature = "chrono")]
2047 copy: get_first_instant, Instant, DateTime<Utc>, DataType::Instant
2048 }
2049
2050 impl_get_first_value! {
2051 /// Get the first big integer value
2052 ///
2053 /// # Returns
2054 ///
2055 /// If types match and a value exists, returns the first big integer
2056 /// value; see `# Errors`.
2057 #[cfg(feature = "big-integer")]
2058 ref: get_first_biginteger, BigInteger, BigInt, DataType::BigInteger, |v: &BigInt| v.clone()
2059 }
2060
2061 impl_get_first_value! {
2062 /// Get the first big decimal value
2063 ///
2064 /// # Returns
2065 ///
2066 /// If types match and a value exists, returns the first big decimal
2067 /// value; see `# Errors`.
2068 #[cfg(feature = "big-decimal")]
2069 ref: get_first_bigdecimal, BigDecimal, BigDecimal, DataType::BigDecimal, |v: &BigDecimal| v.clone()
2070 }
2071
2072 impl_get_first_value! {
2073 /// Get the first Duration value
2074 ///
2075 /// # Returns
2076 ///
2077 /// The first duration when the stored type matches.
2078 copy: get_first_duration, Duration, Duration, DataType::Duration
2079 }
2080
2081 impl_get_first_value! {
2082 /// Get the first Url value
2083 ///
2084 /// # Returns
2085 ///
2086 /// A clone of the first URL when the stored type matches.
2087 #[cfg(feature = "url")]
2088 ref: get_first_url, Url, Url, DataType::Url, |v: &Url| v.clone()
2089 }
2090
2091 impl_get_first_value! {
2092 /// Get the first StringMap value
2093 ///
2094 /// # Returns
2095 ///
2096 /// A clone of the first string map when the stored type matches.
2097 ref: get_first_string_map, StringMap, HashMap<String, String>, DataType::StringMap, |v: &HashMap<String, String>| v.clone()
2098 }
2099
2100 impl_get_first_value! {
2101 /// Get the first Json value
2102 ///
2103 /// # Returns
2104 ///
2105 /// A clone of the first JSON value when the stored type matches.
2106 #[cfg(feature = "json")]
2107 ref: get_first_json, Json, serde_json::Value, DataType::Json, |v: &serde_json::Value| v.clone()
2108 }
2109
2110 // ========================================================================
2111 // Get all values (type checking)
2112 // ========================================================================
2113
2114 impl_get_multi_values! {
2115 /// Get reference to all boolean values
2116 ///
2117 /// # Returns
2118 ///
2119 /// If types match, returns a reference to the boolean value array; see `# Errors`.
2120 ///
2121 /// # Examples
2122 ///
2123 /// ```rust
2124 /// use qubit_value::MultiValues;
2125 ///
2126 /// let values = MultiValues::Bool(vec![true, false, true]);
2127 /// assert_eq!(values.get_bools().unwrap(), &[true, false, true]);
2128 /// ```
2129 slice: get_bools, Bool, bool, DataType::Bool
2130 }
2131
2132 impl_get_multi_values! {
2133 /// Get reference to all character values
2134 ///
2135 /// # Returns
2136 ///
2137 /// If types match, returns a reference to the character value array; see `# Errors`.
2138 slice: get_chars, Char, char, DataType::Char
2139 }
2140
2141 impl_get_multi_values! {
2142 /// Get reference to all int8 values
2143 ///
2144 /// # Returns
2145 ///
2146 /// If types match, returns a reference to the int8 value array; see `# Errors`.
2147 slice: get_int8s, Int8, i8, DataType::Int8
2148 }
2149
2150 impl_get_multi_values! {
2151 /// Get reference to all int16 values
2152 ///
2153 /// # Returns
2154 ///
2155 /// If types match, returns a reference to the int16 value array; see `# Errors`.
2156 slice: get_int16s, Int16, i16, DataType::Int16
2157 }
2158
2159 impl_get_multi_values! {
2160 /// Get reference to all int32 values
2161 ///
2162 /// # Returns
2163 ///
2164 /// If types match, returns a reference to the int32 value array; see `# Errors`.
2165 slice: get_int32s, Int32, i32, DataType::Int32
2166 }
2167
2168 impl_get_multi_values! {
2169 /// Get reference to all int64 values
2170 ///
2171 /// # Returns
2172 ///
2173 /// If types match, returns a reference to the int64 value array; see `# Errors`.
2174 slice: get_int64s, Int64, i64, DataType::Int64
2175 }
2176
2177 impl_get_multi_values! {
2178 /// Get reference to all int128 values
2179 ///
2180 /// # Returns
2181 ///
2182 /// If types match, returns a reference to the int128 value array; see `# Errors`.
2183 slice: get_int128s, Int128, i128, DataType::Int128
2184 }
2185
2186 impl_get_multi_values! {
2187 /// Get reference to all uint8 values
2188 ///
2189 /// # Returns
2190 ///
2191 /// If types match, returns a reference to the uint8 value array; see `# Errors`.
2192 slice: get_uint8s, UInt8, u8, DataType::UInt8
2193 }
2194
2195 impl_get_multi_values! {
2196 /// Get reference to all uint16 values
2197 ///
2198 /// # Returns
2199 ///
2200 /// If types match, returns a reference to the uint16 value array; see `# Errors`.
2201 slice: get_uint16s, UInt16, u16, DataType::UInt16
2202 }
2203
2204 impl_get_multi_values! {
2205 /// Get reference to all uint32 values
2206 ///
2207 /// # Returns
2208 ///
2209 /// If types match, returns a reference to the uint32 value array; see `# Errors`.
2210 slice: get_uint32s, UInt32, u32, DataType::UInt32
2211 }
2212
2213 impl_get_multi_values! {
2214 /// Get reference to all uint64 values
2215 ///
2216 /// # Returns
2217 ///
2218 /// If types match, returns a reference to the uint64 value array; see `# Errors`.
2219 slice: get_uint64s, UInt64, u64, DataType::UInt64
2220 }
2221
2222 impl_get_multi_values! {
2223 /// Get reference to all uint128 values
2224 ///
2225 /// # Returns
2226 ///
2227 /// If types match, returns a reference to the uint128 value array; see `# Errors`.
2228 slice: get_uint128s, UInt128, u128, DataType::UInt128
2229 }
2230
2231 impl_get_multi_values! {
2232 /// Get reference to all float32 values
2233 ///
2234 /// # Returns
2235 ///
2236 /// If types match, returns a reference to the float32 value array; see `# Errors`.
2237 slice: get_float32s, Float32, f32, DataType::Float32
2238 }
2239
2240 impl_get_multi_values! {
2241 /// Get reference to all float64 values
2242 ///
2243 /// # Returns
2244 ///
2245 /// If types match, returns a reference to the float64 value array; see `# Errors`.
2246 slice: get_float64s, Float64, f64, DataType::Float64
2247 }
2248
2249 impl_get_multi_values! {
2250 /// Get reference to all strings
2251 ///
2252 /// # Returns
2253 ///
2254 /// If types match, returns a reference to the string array; otherwise
2255 /// returns an error
2256 vec: get_strings, String, String, DataType::String
2257 }
2258
2259 impl_get_multi_values! {
2260 /// Get reference to all date values
2261 ///
2262 /// # Returns
2263 ///
2264 /// If types match, returns a reference to the date value array; see `# Errors`.
2265 #[cfg(feature = "chrono")]
2266 slice: get_dates, Date, NaiveDate, DataType::Date
2267 }
2268
2269 impl_get_multi_values! {
2270 /// Get reference to all time values
2271 ///
2272 /// # Returns
2273 ///
2274 /// If types match, returns a reference to the time value array; see `# Errors`.
2275 #[cfg(feature = "chrono")]
2276 slice: get_times, Time, NaiveTime, DataType::Time
2277 }
2278
2279 impl_get_multi_values! {
2280 /// Get reference to all datetime values
2281 ///
2282 /// # Returns
2283 ///
2284 /// If types match, returns a reference to the datetime value array; see `# Errors`.
2285 #[cfg(feature = "chrono")]
2286 slice: get_datetimes, DateTime, NaiveDateTime, DataType::DateTime
2287 }
2288
2289 impl_get_multi_values! {
2290 /// Get reference to all UTC instant values
2291 ///
2292 /// # Returns
2293 ///
2294 /// If types match, returns a reference to the UTC instant value array; see `# Errors`.
2295 #[cfg(feature = "chrono")]
2296 slice: get_instants, Instant, DateTime<Utc>, DataType::Instant
2297 }
2298
2299 impl_get_multi_values! {
2300 /// Get reference to all big integers
2301 ///
2302 /// # Returns
2303 ///
2304 /// If types match, returns a reference to the big integer array; see `# Errors`.
2305 #[cfg(feature = "big-integer")]
2306 vec: get_bigintegers, BigInteger, BigInt, DataType::BigInteger
2307 }
2308
2309 impl_get_multi_values! {
2310 /// Get reference to all big decimals
2311 ///
2312 /// # Returns
2313 ///
2314 /// If types match, returns a reference to the big decimal array; see `# Errors`.
2315 #[cfg(feature = "big-decimal")]
2316 vec: get_bigdecimals, BigDecimal, BigDecimal, DataType::BigDecimal
2317 }
2318
2319 impl_get_multi_values! {
2320 /// Get reference to all Duration values
2321 ///
2322 /// # Returns
2323 ///
2324 /// A slice containing all stored durations.
2325 slice: get_durations, Duration, Duration, DataType::Duration
2326 }
2327
2328 impl_get_multi_values! {
2329 /// Get reference to all Url values
2330 ///
2331 /// # Returns
2332 ///
2333 /// A reference to the vector containing all stored URLs.
2334 #[cfg(feature = "url")]
2335 vec: get_urls, Url, Url, DataType::Url
2336 }
2337
2338 impl_get_multi_values! {
2339 /// Get reference to all StringMap values
2340 ///
2341 /// # Returns
2342 ///
2343 /// A reference to the vector containing all stored string maps.
2344 vec: get_string_maps, StringMap, HashMap<String, String>, DataType::StringMap
2345 }
2346
2347 impl_get_multi_values! {
2348 /// Get reference to all Json values
2349 ///
2350 /// # Returns
2351 ///
2352 /// A reference to the vector containing all stored JSON values.
2353 #[cfg(feature = "json")]
2354 vec: get_jsons, Json, serde_json::Value, DataType::Json
2355 }
2356}