Skip to main content

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