qubit_value/multi_values/multi_values_core.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
9//! Core generic accessors and state methods for `MultiValues`.
10
11use qubit_datatype::DataType;
12
13use crate::value_error::{
14 ValueError,
15 ValueResult,
16};
17use crate::{
18 IntoValueDefault,
19 Value,
20};
21
22use super::multi_values::{
23 MultiValues,
24 MultiValuesRepr,
25};
26use crate::value::ValueRepr;
27
28macro_rules! multi_values_data_type_match {
29 ($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)),+ $(,)?) => {
30 match &$value.repr {
31 MultiValuesRepr::Unset(dt) => *dt,
32 $($(#[$cfg])* MultiValuesRepr::$variant(_) => $data_type,)+
33 }
34 };
35}
36
37macro_rules! multi_values_count_match {
38 ($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)),+ $(,)?) => {
39 match &$value.repr {
40 MultiValuesRepr::Unset(_) => 0,
41 $($(#[$cfg])* MultiValuesRepr::$variant(values) => values.len(),)+
42 }
43 };
44}
45
46macro_rules! multi_values_clear_match {
47 ($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)),+ $(,)?) => {
48 match &mut $value.repr {
49 MultiValuesRepr::Unset(_) => {}
50 $($(#[$cfg])* MultiValuesRepr::$variant(values) => values.clear(),)+
51 }
52 };
53}
54
55macro_rules! multi_values_append_match {
56 ($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)),+ $(,)?) => {
57 match (&mut $left.repr, &mut $right.repr) {
58 $(
59 $(#[$cfg])*
60 (MultiValuesRepr::$variant(values), MultiValuesRepr::$variant(other_values)) => {
61 values.append(other_values);
62 }
63 )+
64 (slot @ MultiValuesRepr::Unset(_), other_values) => {
65 *slot = std::mem::replace(other_values, MultiValuesRepr::Unset(DataType::String));
66 }
67 _ => unreachable!(),
68 }
69 };
70}
71
72macro_rules! multi_values_first_value_match {
73 ($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)),+ $(,)?) => {
74 match &$value.repr {
75 MultiValuesRepr::Unset(data_type) => Value::new_unset(*data_type),
76 $(
77 $(#[$cfg])*
78 MultiValuesRepr::$variant(values) => values
79 .first()
80 .map(|value| materialize_stored!($materialization, value))
81 .map(Value::$variant)
82 .unwrap_or(Value::new_unset($data_type)),
83 )+
84 }
85 };
86}
87
88macro_rules! multi_values_into_first_value_match {
89 ($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)),+ $(,)?) => {
90 match $value.repr {
91 MultiValuesRepr::Unset(data_type) => Value::new_unset(data_type),
92 $(
93 $(#[$cfg])*
94 MultiValuesRepr::$variant(values) => values
95 .into_iter()
96 .next()
97 .map(Value::$variant)
98 .unwrap_or(Value::new_unset($data_type)),
99 )+
100 }
101 };
102}
103
104macro_rules! multi_values_merge_match {
105 ($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)),+ $(,)?) => {
106 match (&mut $left.repr, &$right.repr) {
107 $(
108 $(#[$cfg])*
109 (MultiValuesRepr::$variant(values), MultiValuesRepr::$variant(other_values)) => {
110 values.extend_from_slice(other_values)
111 }
112 )+
113 (slot @ MultiValuesRepr::Unset(_), other_values) => *slot = other_values.clone(),
114 _ => unreachable!(),
115 }
116 };
117}
118
119macro_rules! value_into_multi_values_match {
120 ($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)),+ $(,)?) => {
121 match $value.repr {
122 ValueRepr::Unset(data_type) => MultiValues::new_unset(data_type),
123 $($(#[$cfg])* ValueRepr::$variant(value) => {
124 MultiValues::$variant(vec![value_storage_into_multi!($variant, value)])
125 },)+
126 }
127 };
128}
129
130impl MultiValues {
131 /// Generic constructor method
132 ///
133 /// Creates `MultiValues` from any supported input form, avoiding direct
134 /// use of enum variants at call sites.
135 ///
136 /// Supported input forms include single values, vectors, slices, arrays,
137 /// borrowed vectors, and borrowed string collections for supported element
138 /// types.
139 ///
140 /// # Type Parameters
141 ///
142 /// * `S` - Input type convertible into [`MultiValues`].
143 ///
144 /// # Parameters
145 ///
146 /// * `values` - Values to convert into a collection.
147 ///
148 /// # Returns
149 ///
150 /// Returns `MultiValues` wrapping the converted input values.
151 ///
152 /// # Examples
153 ///
154 /// ```rust
155 /// use qubit_value::MultiValues;
156 ///
157 /// // Basic types
158 /// let mv = MultiValues::new(vec![1, 2, 3]);
159 /// assert_eq!(mv.len(), 3);
160 ///
161 /// // Strings
162 /// let mv = MultiValues::new(vec!["a".to_string(), "b".to_string()]);
163 /// assert_eq!(mv.len(), 2);
164 /// ```
165 #[inline(always)]
166 pub fn new<S>(values: S) -> Self
167 where
168 S: Into<Self>,
169 {
170 values.into()
171 }
172
173 /// Generic getter method for multiple values.
174 ///
175 /// Performs a strict typed read of all stored values as `Vec<T>`.
176 ///
177 /// # Type Parameters
178 ///
179 /// * `T` - The target element type to retrieve.
180 ///
181 /// # Returns
182 ///
183 /// Returns the list of values when the stored type matches `T`.
184 ///
185 /// # Errors
186 ///
187 /// Returns [`ValueError::Missing`] when the container is unset with the
188 /// requested type, or [`ValueError::TypeMismatch`] when the stored type
189 /// differs from `T`.
190 ///
191 /// # Examples
192 ///
193 /// ```rust
194 /// use qubit_value::MultiValues;
195 ///
196 /// let multi = MultiValues::Int32(vec![1, 2, 3]);
197 ///
198 /// // Through type inference
199 /// let nums: Vec<i32> = multi.get().unwrap();
200 /// assert_eq!(nums, vec![1, 2, 3]);
201 ///
202 /// // Explicitly specify type parameter
203 /// let nums = multi.get::<i32>().unwrap();
204 /// assert_eq!(nums, vec![1, 2, 3]);
205 /// ```
206 #[inline(always)]
207 pub fn get<T>(&self) -> ValueResult<Vec<T>>
208 where
209 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
210 {
211 Vec::<T>::try_from(self)
212 }
213
214 /// Generic getter method with a default value list.
215 ///
216 /// Returns the supplied default only when this container is unset. A
217 /// concrete empty vector remains an empty result.
218 ///
219 /// # Type Parameters
220 ///
221 /// * `T` - Target element type for the strict read.
222 ///
223 /// # Parameters
224 ///
225 /// * `default` - Lazily materialized list used only for unset storage.
226 ///
227 /// # Returns
228 ///
229 /// The concrete stored list, or `default` for unset storage.
230 ///
231 /// # Errors
232 ///
233 /// Returns [`ValueError::TypeMismatch`] when the stored type differs from
234 /// `T`.
235 #[inline]
236 pub fn get_or<T>(
237 &self,
238 default: impl IntoValueDefault<Vec<T>>,
239 ) -> ValueResult<Vec<T>>
240 where
241 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
242 {
243 match self.get() {
244 Err(ValueError::Missing(missing)) if missing.is_unset() => {
245 Ok(default.into_value_default())
246 }
247 result => result,
248 }
249 }
250
251 /// Strictly reads all values or calls `default` only when storage is unset.
252 ///
253 /// A concrete empty collection is returned unchanged and type mismatches
254 /// are preserved without invoking the callback.
255 ///
256 /// # Type Parameters
257 ///
258 /// * `T` - Target element type.
259 /// * `F` - Deferred fallback producing the complete list.
260 ///
261 /// # Parameters
262 ///
263 /// * `default` - Callback invoked only for unset storage.
264 ///
265 /// # Returns
266 ///
267 /// The stored list or the callback result.
268 ///
269 /// # Errors
270 ///
271 /// Returns [`ValueError::TypeMismatch`] for an incompatible concrete
272 /// collection without invoking the callback.
273 #[inline]
274 pub fn get_or_else<T, F>(&self, default: F) -> ValueResult<Vec<T>>
275 where
276 for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
277 F: FnOnce() -> Vec<T>,
278 {
279 match self.get() {
280 Err(ValueError::Missing(missing)) if missing.is_unset() => {
281 Ok(default())
282 }
283 result => result,
284 }
285 }
286
287 /// Generic getter method for the first value
288 ///
289 /// Reads the first stored value as `T`, performing strict type checking.
290 ///
291 /// `get_first<T>()` does not do cross-type conversion. When the `converter`
292 /// feature is enabled, use `to<T>()` for compatible cross-type conversion.
293 ///
294 /// # Type Parameters
295 ///
296 /// * `T` - The target element type to retrieve.
297 ///
298 /// # Returns
299 ///
300 /// Returns the first value when the stored type matches `T` and at least
301 /// one value exists.
302 ///
303 /// # Errors
304 ///
305 /// Returns [`ValueError::Missing`] when the requested type matches but no
306 /// value is stored, or [`ValueError::TypeMismatch`] when the stored type
307 /// differs from `T`.
308 ///
309 /// # Examples
310 ///
311 /// ```rust
312 /// use qubit_value::MultiValues;
313 ///
314 /// let multi = MultiValues::Int32(vec![42, 100, 200]);
315 ///
316 /// // Through type inference
317 /// let first: i32 = multi.get_first().unwrap();
318 /// assert_eq!(first, 42);
319 ///
320 /// // Explicitly specify type parameter
321 /// let first = multi.get_first::<i32>().unwrap();
322 /// assert_eq!(first, 42);
323 ///
324 /// // String type
325 /// let multi = MultiValues::String(vec!["hello".to_string(), "world".to_string()]);
326 /// let first: String = multi.get_first().unwrap();
327 /// assert_eq!(first, "hello");
328 /// ```
329 #[inline(always)]
330 pub fn get_first<T>(&self) -> ValueResult<T>
331 where
332 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
333 {
334 T::try_from(self)
335 }
336
337 /// Generic first-value getter with a default value.
338 ///
339 /// Returns the supplied default only when the container is unset. A
340 /// concrete empty vector returns [`ValueError::Missing`]; type mismatches
341 /// are also preserved.
342 ///
343 /// # Type Parameters
344 ///
345 /// * `T` - Target type for the strict first-item read.
346 ///
347 /// # Parameters
348 ///
349 /// * `default` - Lazily materialized value used only for unset storage.
350 ///
351 /// # Returns
352 ///
353 /// The first concrete item, or `default` for unset storage.
354 ///
355 /// # Errors
356 ///
357 /// Returns [`ValueError::Missing`] for a concrete empty collection or
358 /// [`ValueError::TypeMismatch`] when the stored type differs from `T`.
359 #[inline]
360 pub fn get_first_or<T>(
361 &self,
362 default: impl IntoValueDefault<T>,
363 ) -> ValueResult<T>
364 where
365 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
366 {
367 match self.get_first() {
368 Err(ValueError::Missing(missing)) if missing.is_unset() => {
369 Ok(default.into_value_default())
370 }
371 result => result,
372 }
373 }
374
375 /// Strictly reads the first value or calls `default` only when unset.
376 ///
377 /// # Type Parameters
378 ///
379 /// * `T` - Target element type.
380 /// * `F` - Deferred fallback producing one element.
381 ///
382 /// # Parameters
383 ///
384 /// * `default` - Callback invoked only for unset storage.
385 ///
386 /// # Returns
387 ///
388 /// The first stored item or the callback result.
389 ///
390 /// # Errors
391 ///
392 /// Preserves empty-collection and type-mismatch errors without invoking
393 /// the callback.
394 #[inline]
395 pub fn get_first_or_else<T, F>(&self, default: F) -> ValueResult<T>
396 where
397 for<'a> T: TryFrom<&'a Self, Error = ValueError>,
398 F: FnOnce() -> T,
399 {
400 match self.get_first() {
401 Err(ValueError::Missing(missing)) if missing.is_unset() => {
402 Ok(default())
403 }
404 result => result,
405 }
406 }
407
408 /// Generic setter method
409 ///
410 /// Replaces the entire list with the converted input values.
411 ///
412 /// This operation updates the stored type to the input element type and
413 /// does not validate runtime compatibility with the previous variant.
414 ///
415 /// Supports any input that can be converted into [`MultiValues`], including
416 /// single values, vectors, slices, arrays, and borrowed vectors for
417 /// supported element types.
418 ///
419 /// Existing values are replaced, and the stored type becomes the converted
420 /// input type.
421 ///
422 /// # Type Parameters
423 ///
424 /// * `S` - Input type convertible into [`MultiValues`].
425 ///
426 /// # Parameters
427 ///
428 /// * `values` - The values to set.
429 ///
430 /// # Compile-time restriction
431 ///
432 /// Unsupported input types fail to compile because they do not implement
433 /// `Into<MultiValues>`.
434 ///
435 /// # Examples
436 ///
437 /// ```rust
438 /// use qubit_datatype::DataType;
439 /// use qubit_value::MultiValues;
440 ///
441 /// // 1) Vec<T>
442 /// let mut mv = MultiValues::Unset(DataType::Int32);
443 /// mv.set(vec![42, 100, 200]);
444 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200]);
445 ///
446 /// // 2) &[T]
447 /// let mut mv = MultiValues::Unset(DataType::Int32);
448 /// let slice = &[7, 8, 9][..];
449 /// mv.set(slice);
450 /// assert_eq!(mv.get_int32s().unwrap(), &[7, 8, 9]);
451 ///
452 /// // 3) Single T
453 /// let mut mv = MultiValues::Unset(DataType::Int32);
454 /// mv.set(42);
455 /// assert_eq!(mv.get_int32s().unwrap(), &[42]);
456 ///
457 /// // String example
458 /// let mut mv = MultiValues::Unset(DataType::String);
459 /// mv.set(vec!["hello".to_string(), "world".to_string()]);
460 /// assert_eq!(mv.get_strings().unwrap(), &["hello", "world"]);
461 /// ```
462 #[inline(always)]
463 pub fn set<S>(&mut self, values: S)
464 where
465 S: Into<Self>,
466 {
467 *self = values.into();
468 }
469
470 /// Generic add method
471 ///
472 /// Appends converted input values to the existing list with strict type
473 /// checking.
474 ///
475 /// Supports any input that can be converted into [`MultiValues`], including
476 /// single values, vectors, slices, arrays, and borrowed vectors for
477 /// supported element types.
478 ///
479 /// The converted input must have the same data type as the current
480 /// container. An empty container keeps its declared type until
481 /// non-empty values of the same type are appended.
482 ///
483 /// # Type Parameters
484 ///
485 /// * `S` - Input type convertible into [`MultiValues`].
486 ///
487 /// # Parameters
488 ///
489 /// * `values` - Values to append.
490 ///
491 /// # Returns
492 ///
493 /// `Ok(())` after appending, including when the input is empty.
494 ///
495 /// # Errors
496 ///
497 /// Returns [`ValueError::TypeMismatch`] when the converted input data type
498 /// differs from the current container data type.
499 ///
500 /// # Examples
501 ///
502 /// ```rust
503 /// use qubit_datatype::DataType;
504 /// use qubit_value::MultiValues;
505 ///
506 /// // 1) Single T
507 /// let mut mv = MultiValues::Int32(vec![42]);
508 /// mv.add(100).unwrap();
509 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100]);
510 ///
511 /// // 2) Vec<T>
512 /// mv.add(vec![200, 300]).unwrap();
513 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300]);
514 ///
515 /// // 3) &[T]
516 /// let slice = &[400, 500][..];
517 /// mv.add(slice).unwrap();
518 /// assert_eq!(mv.get_int32s().unwrap(), &[42, 100, 200, 300, 400, 500]);
519 /// ```
520 pub fn add<S>(&mut self, values: S) -> ValueResult<()>
521 where
522 S: Into<Self>,
523 {
524 let mut other = values.into();
525 if self.data_type() != other.data_type() {
526 return Err(ValueError::TypeMismatch {
527 expected: self.data_type(),
528 actual: other.data_type(),
529 });
530 }
531 if other.is_empty() {
532 return Ok(());
533 }
534
535 for_each_value_type!(multi_values_append_match, self, other);
536
537 Ok(())
538 }
539
540 /// Get the data type of the values
541 ///
542 /// # Returns
543 ///
544 /// Returns the data type corresponding to these multiple values
545 ///
546 /// # Examples
547 ///
548 /// ```rust
549 /// use qubit_datatype::DataType;
550 /// use qubit_value::MultiValues;
551 ///
552 /// let values = MultiValues::Int32(vec![1, 2, 3]);
553 /// assert_eq!(values.data_type(), DataType::Int32);
554 /// ```
555 #[inline(always)]
556 pub fn data_type(&self) -> DataType {
557 for_each_value_type!(multi_values_data_type_match, self)
558 }
559
560 /// Returns the number of values.
561 ///
562 /// # Returns
563 ///
564 /// The number of values contained in these multiple values. An unset
565 /// collection has length zero.
566 ///
567 /// # Examples
568 ///
569 /// ```rust
570 /// use qubit_datatype::DataType;
571 /// use qubit_value::MultiValues;
572 ///
573 /// let values = MultiValues::Int32(vec![1, 2, 3]);
574 /// assert_eq!(values.len(), 3);
575 ///
576 /// let empty = MultiValues::Unset(DataType::String);
577 /// assert_eq!(empty.len(), 0);
578 /// ```
579 #[inline(always)]
580 #[must_use]
581 pub fn len(&self) -> usize {
582 for_each_value_type!(multi_values_count_match, self)
583 }
584
585 /// Tests whether this collection contains no values.
586 ///
587 /// An unset collection and a concrete empty vector both have length zero.
588 /// Use [`MultiValues::is_unset`] when the distinction between no collection
589 /// and a concrete empty collection matters.
590 ///
591 /// # Returns
592 ///
593 /// `true` when [`Self::len`] is zero; otherwise, `false`.
594 #[inline(always)]
595 #[must_use]
596 pub fn is_empty(&self) -> bool {
597 self.len() == 0
598 }
599
600 /// Tests whether this container has no concrete vector.
601 ///
602 /// # Returns
603 ///
604 /// Returns `true` only for [`MultiValues::Unset`]. A concrete empty vector
605 /// returns `false`.
606 ///
607 /// # Examples
608 ///
609 /// ```rust
610 /// use qubit_datatype::DataType;
611 /// use qubit_value::MultiValues;
612 ///
613 /// let values = MultiValues::Int32(vec![]);
614 /// assert!(!values.is_unset());
615 ///
616 /// let empty = MultiValues::Unset(DataType::String);
617 /// assert!(empty.is_unset());
618 /// ```
619 #[inline(always)]
620 #[must_use]
621 pub fn is_unset(&self) -> bool {
622 matches!(self.repr, MultiValuesRepr::Unset(_))
623 }
624
625 /// Tests whether a concrete collection belongs to the numeric type family.
626 ///
627 /// A concrete empty numeric vector returns `true`; an unset collection
628 /// returns `false`, even when its declared type is numeric.
629 ///
630 /// # Returns
631 ///
632 /// `true` for concrete collections with a numeric element type.
633 #[inline(always)]
634 #[must_use]
635 pub fn is_numeric(&self) -> bool {
636 !self.is_unset() && self.data_type().is_numeric()
637 }
638
639 /// Removes the concrete vector while preserving its declared data type.
640 #[inline(always)]
641 pub fn unset(&mut self) {
642 *self = MultiValues::new_unset(self.data_type());
643 }
644
645 /// Clears all values while preserving a concrete collection and its type.
646 /// An unset collection remains unset because it has no concrete vector to
647 /// clear.
648 ///
649 /// # Examples
650 ///
651 /// ```rust
652 /// use qubit_datatype::DataType;
653 /// use qubit_value::MultiValues;
654 ///
655 /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
656 /// values.clear();
657 /// assert_eq!(values.len(), 0);
658 /// assert_eq!(values.data_type(), DataType::Int32);
659 /// ```
660 #[inline(always)]
661 pub fn clear(&mut self) {
662 for_each_value_type!(multi_values_clear_match, self)
663 }
664
665 /// Set the data type
666 ///
667 /// If the new type differs from the current type, clears all values and
668 /// sets the new type.
669 ///
670 /// # Parameters
671 ///
672 /// * `data_type` - The data type to set
673 ///
674 /// # Examples
675 ///
676 /// ```rust
677 /// use qubit_datatype::DataType;
678 /// use qubit_value::MultiValues;
679 ///
680 /// let mut values = MultiValues::Int32(vec![1, 2, 3]);
681 /// values.set_type(DataType::String);
682 /// assert!(values.is_unset());
683 /// assert_eq!(values.data_type(), DataType::String);
684 /// ```
685 #[inline]
686 pub fn set_type(&mut self, data_type: DataType) {
687 if self.data_type() != data_type {
688 *self = MultiValues::new_unset(data_type);
689 }
690 }
691
692 /// Converts the first element to a single [`Value`].
693 ///
694 /// Returns `Value::Unset` with the same declared type when no element is
695 /// stored.
696 ///
697 /// # Returns
698 ///
699 /// A cloned first item, or a typed unset value when no item exists.
700 pub fn first_value(&self) -> Value {
701 for_each_value_type!(multi_values_first_value_match, self)
702 }
703
704 /// Consumes this collection and returns its first item as a [`Value`].
705 ///
706 /// Empty and unset collections become [`Value::Unset`] with the same data
707 /// type. Owned element storage is moved instead of cloned.
708 ///
709 /// # Returns
710 ///
711 /// The owned first item, or a typed unset value when no item exists.
712 pub fn into_first_value(self) -> Value {
713 for_each_value_type!(multi_values_into_first_value_match, self)
714 }
715
716 /// Appends all values from another container with the same data type.
717 ///
718 /// # Parameters
719 ///
720 /// * `other` - Collection whose values are cloned and appended.
721 ///
722 /// # Returns
723 ///
724 /// `Ok(())` after appending, including when `other` is empty.
725 ///
726 /// # Errors
727 ///
728 /// Returns [`ValueError::TypeMismatch`] when `other` has a different data
729 /// type.
730 pub fn merge(&mut self, other: &MultiValues) -> ValueResult<()> {
731 if self.data_type() != other.data_type() {
732 return Err(ValueError::TypeMismatch {
733 expected: self.data_type(),
734 actual: other.data_type(),
735 });
736 }
737 if other.is_empty() {
738 return Ok(());
739 }
740 for_each_value_type!(multi_values_merge_match, self, other);
741 Ok(())
742 }
743}
744
745impl From<Value> for MultiValues {
746 fn from(value: Value) -> Self {
747 for_each_value_type!(value_into_multi_values_match, value)
748 }
749}