value_bag/internal/
seq.rs

1use crate::{
2    fill::Slot,
3    internal::{Internal, InternalVisitor},
4    std::{any::Any, fmt, marker::PhantomData, mem, ops::ControlFlow},
5    Error, ValueBag,
6};
7
8#[cfg(feature = "alloc")]
9use crate::std::{string::String, vec::Vec};
10
11impl<'v> ValueBag<'v> {
12    /// Get a value from a sequence of values without capturing support.
13    pub fn from_seq_slice<I, T>(value: &'v I) -> Self
14    where
15        I: AsRef<[T]>,
16        &'v T: Into<ValueBag<'v>> + 'v,
17    {
18        ValueBag {
19            inner: Internal::AnonSeq(SeqSlice::new_ref(value)),
20        }
21    }
22
23    pub(crate) const fn from_dyn_seq(value: &'v dyn Seq) -> Self {
24        ValueBag {
25            inner: Internal::AnonSeq(value),
26        }
27    }
28
29    /// Try get a collection `S` of `u64`s from this value.
30    ///
31    /// If this value is a sequence then the collection `S` will be extended
32    /// with the attempted conversion of each of its elements.
33    ///
34    /// If this value is not a sequence then this method will return `None`.
35    pub fn to_u64_seq<S: Default + Extend<Option<u64>>>(&self) -> Option<S> {
36        self.inner
37            .extend::<ExtendPrimitive<S, u64>>()
38            .map(|seq| seq.into_inner())
39    }
40
41    /// Try get a collection `S` of `i64`s from this value.
42    ///
43    /// If this value is a sequence then the collection `S` will be extended
44    /// with the attempted conversion of each of its elements.
45    ///
46    /// If this value is not a sequence then this method will return `None`.
47    pub fn to_i64_seq<S: Default + Extend<Option<i64>>>(&self) -> Option<S> {
48        self.inner
49            .extend::<ExtendPrimitive<S, i64>>()
50            .map(|seq| seq.into_inner())
51    }
52
53    /// Try get a collection `S` of `u128`s from this value.
54    ///
55    /// If this value is a sequence then the collection `S` will be extended
56    /// with the attempted conversion of each of its elements.
57    ///
58    /// If this value is not a sequence then this method will return `None`.
59    pub fn to_u128_seq<S: Default + Extend<Option<u128>>>(&self) -> Option<S> {
60        self.inner
61            .extend::<ExtendPrimitive<S, u128>>()
62            .map(|seq| seq.into_inner())
63    }
64
65    /// Try get a collection `S` of `i128`s from this value.
66    ///
67    /// If this value is a sequence then the collection `S` will be extended
68    /// with the attempted conversion of each of its elements.
69    ///
70    /// If this value is not a sequence then this method will return `None`.
71    pub fn to_i128_seq<S: Default + Extend<Option<i128>>>(&self) -> Option<S> {
72        self.inner
73            .extend::<ExtendPrimitive<S, i128>>()
74            .map(|seq| seq.into_inner())
75    }
76
77    /// Try get a collection `S` of `f64`s from this value.
78    ///
79    /// If this value is a sequence then the collection `S` will be extended
80    /// with the attempted conversion of each of its elements.
81    ///
82    /// If this value is not a sequence then this method will return `None`.
83    pub fn to_f64_seq<S: Default + Extend<Option<f64>>>(&self) -> Option<S> {
84        self.inner
85            .extend::<ExtendPrimitive<S, f64>>()
86            .map(|seq| seq.into_inner())
87    }
88
89    /// Get a collection `S` of `f64`s from this value.
90    ///
91    /// If this value is a sequence then the collection `S` will be extended
92    /// with the conversion of each of its elements. The conversion is the
93    /// same as [`ValueBag::as_f64`].
94    ///
95    /// If this value is not a sequence then this method will return an
96    /// empty collection.
97    ///
98    /// This is similar to [`ValueBag::to_f64_seq`], but can be more
99    /// convenient when there's no need to distinguish between an empty
100    /// collection and a non-collection, or between `f64` and non-`f64` elements.
101    pub fn as_f64_seq<S: Default + Extend<f64>>(&self) -> S {
102        #[derive(Default)]
103        struct ExtendF64<S>(S);
104
105        impl<'a, S: Extend<f64>> ExtendValue<'a> for ExtendF64<S> {
106            fn extend(&mut self, inner: Internal<'_>) {
107                self.0.extend(Some(ValueBag { inner }.as_f64()))
108            }
109        }
110
111        self.inner
112            .extend::<ExtendF64<S>>()
113            .map(|seq| seq.0)
114            .unwrap_or_default()
115    }
116
117    /// Try get a collection `S` of `bool`s from this value.
118    ///
119    /// If this value is a sequence then the collection `S` will be extended
120    /// with the attempted conversion of each of its elements.
121    ///
122    /// If this value is not a sequence then this method will return `None`.
123    pub fn to_bool_seq<S: Default + Extend<Option<bool>>>(&self) -> Option<S> {
124        self.inner
125            .extend::<ExtendPrimitive<S, bool>>()
126            .map(|seq| seq.into_inner())
127    }
128
129    /// Try get a collection `S` of `char`s from this value.
130    ///
131    /// If this value is a sequence then the collection `S` will be extended
132    /// with the attempted conversion of each of its elements.
133    ///
134    /// If this value is not a sequence then this method will return `None`.
135    pub fn to_char_seq<S: Default + Extend<Option<char>>>(&self) -> Option<S> {
136        self.inner
137            .extend::<ExtendPrimitive<S, char>>()
138            .map(|seq| seq.into_inner())
139    }
140
141    /// Try get a collection `S` of strings from this value.
142    ///
143    /// If this value is a sequence then the collection `S` will be extended
144    /// with the attempted conversion of each of its elements.
145    ///
146    /// If this value is not a sequence then this method will return `None`.
147    #[inline]
148    pub fn to_borrowed_str_seq<S: Default + Extend<Option<&'v str>>>(&self) -> Option<S> {
149        #[derive(Default)]
150        struct ExtendStr<'a, S>(S, PhantomData<&'a str>);
151
152        impl<'a, S: Extend<Option<&'a str>>> ExtendValue<'a> for ExtendStr<'a, S> {
153            fn extend<'b>(&mut self, _: Internal<'b>) {
154                self.0.extend(Some(None::<&'a str>))
155            }
156
157            fn extend_borrowed(&mut self, inner: Internal<'a>) {
158                self.0.extend(Some(ValueBag { inner }.to_borrowed_str()))
159            }
160        }
161
162        self.inner.extend::<ExtendStr<'v, S>>().map(|seq| seq.0)
163    }
164}
165
166impl<'s, 'f> Slot<'s, 'f> {
167    /// Fill the slot with a sequence of values.
168    ///
169    /// The given value doesn't need to satisfy any particular lifetime constraints.
170    pub fn fill_seq_slice<I, T>(self, value: &'f I) -> Result<(), Error>
171    where
172        I: AsRef<[T]>,
173        &'f T: Into<ValueBag<'f>> + 'f,
174    {
175        self.fill(|visitor| visitor.seq(SeqSlice::new_ref(value)))
176    }
177}
178
179/*
180This is a bit of an ugly way of working around the gulf between
181lifetimes expressed externally as bounds, and lifetimes implied
182on methods.
183*/
184
185#[repr(transparent)]
186struct SeqSlice<'a, I: ?Sized, T>(PhantomData<&'a [T]>, I);
187
188impl<'a, I: AsRef<[T]> + ?Sized + 'a, T> SeqSlice<'a, I, T> {
189    fn new_ref(v: &'a I) -> &'a SeqSlice<'a, I, T> {
190        // SAFETY: `SeqSlice<'a, I, T>` and `I` have the same ABI
191        unsafe { &*(v as *const I as *const SeqSlice<'a, I, T>) }
192    }
193
194    fn as_ref<'b>(&'b self) -> &'a [T] {
195        // SAFETY: `new_ref` requires there's a borrow of `&'a I`
196        // on the borrow stack, so we can safely borrow it for `'a` here
197        let inner = unsafe { mem::transmute::<&'b I, &'a I>(&self.1) };
198
199        inner.as_ref()
200    }
201}
202
203impl<'a, I, T> Seq for SeqSlice<'a, I, T>
204where
205    I: AsRef<[T]> + ?Sized + 'a,
206    &'a T: Into<ValueBag<'a>>,
207{
208    fn visit(&self, visitor: &mut dyn Visitor<'_>) {
209        for v in self.as_ref().iter() {
210            if let ControlFlow::Break(()) = visitor.element(v.into()) {
211                return;
212            }
213        }
214    }
215
216    fn borrowed_visit<'v>(&'v self, visitor: &mut dyn Visitor<'v>) {
217        for v in self.as_ref().iter() {
218            if let ControlFlow::Break(()) = visitor.borrowed_element(v.into()) {
219                return;
220            }
221        }
222    }
223}
224
225pub(crate) trait Seq {
226    fn visit(&self, visitor: &mut dyn Visitor<'_>);
227
228    fn borrowed_visit<'v>(&'v self, visitor: &mut dyn Visitor<'v>) {
229        self.visit(visitor)
230    }
231}
232
233impl<'a, S: Seq + ?Sized> Seq for &'a S {
234    fn visit(&self, visitor: &mut dyn Visitor<'_>) {
235        (**self).visit(visitor)
236    }
237
238    fn borrowed_visit<'v>(&'v self, visitor: &mut dyn Visitor<'v>) {
239        (**self).borrowed_visit(visitor)
240    }
241}
242
243pub(crate) trait Visitor<'v> {
244    fn element(&mut self, v: ValueBag) -> ControlFlow<()>;
245
246    fn borrowed_element(&mut self, v: ValueBag<'v>) -> ControlFlow<()> {
247        self.element(v)
248    }
249}
250
251impl<'a, 'v, T: Visitor<'v> + ?Sized> Visitor<'v> for &'a mut T {
252    fn element(&mut self, v: ValueBag) -> ControlFlow<()> {
253        (**self).element(v)
254    }
255
256    fn borrowed_element(&mut self, v: ValueBag<'v>) -> ControlFlow<()> {
257        (**self).borrowed_element(v)
258    }
259}
260
261pub(crate) trait DowncastSeq {
262    // Currently only used when `owned` is also available
263    #[allow(dead_code)]
264    fn as_any(&self) -> &dyn Any;
265    fn as_super(&self) -> &dyn Seq;
266}
267
268impl<T: Seq + 'static> DowncastSeq for T {
269    fn as_any(&self) -> &dyn Any {
270        self
271    }
272
273    fn as_super(&self) -> &dyn Seq {
274        self
275    }
276}
277
278impl<'a> Seq for dyn DowncastSeq + Send + Sync + 'a {
279    fn visit(&self, visitor: &mut dyn Visitor<'_>) {
280        self.as_super().visit(visitor)
281    }
282}
283
284macro_rules! convert_primitive(
285    ($($t:ty,)*) => {
286        $(
287            impl<'v, const N: usize> From<&'v [$t; N]> for ValueBag<'v> {
288                fn from(v: &'v [$t; N]) -> Self {
289                    ValueBag::from_seq_slice(v)
290                }
291            }
292
293            impl<'v, const N: usize> From<Option<&'v [$t; N]>> for ValueBag<'v> {
294                fn from(v: Option<&'v [$t; N]>) -> Self {
295                    ValueBag::from_option(v)
296                }
297            }
298
299            impl<'a, 'v> From<&'v &'a [$t]> for ValueBag<'v> {
300                fn from(v: &'v &'a [$t]) -> Self {
301                    ValueBag::from_seq_slice(v)
302                }
303            }
304
305            impl<'a, 'v> From<Option<&'v &'a [$t]>> for ValueBag<'v> {
306                fn from(v: Option<&'v &'a [$t]>) -> Self {
307                    ValueBag::from_option(v)
308                }
309            }
310
311            #[cfg(feature = "alloc")]
312            impl<'v> From<&'v Vec<$t>> for ValueBag<'v> {
313                fn from(v: &'v Vec<$t>) -> Self {
314                    ValueBag::from_seq_slice(v)
315                }
316            }
317
318            #[cfg(feature = "alloc")]
319            impl<'v> From<Option<&'v Vec<$t>>> for ValueBag<'v> {
320                fn from(v: Option<&'v Vec<$t>>) -> Self {
321                    ValueBag::from_option(v)
322                }
323            }
324        )*
325    }
326);
327
328convert_primitive![
329    u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64, bool, char,
330];
331
332impl<'v, 'a, const N: usize> From<&'v [&'a str; N]> for ValueBag<'v> {
333    fn from(v: &'v [&'a str; N]) -> Self {
334        ValueBag::from_seq_slice(v)
335    }
336}
337
338impl<'v, 'a, const N: usize> From<Option<&'v [&'a str; N]>> for ValueBag<'v> {
339    fn from(v: Option<&'v [&'a str; N]>) -> Self {
340        ValueBag::from_option(v)
341    }
342}
343
344impl<'v, 'a, 'b> From<&'v &'a [&'b str]> for ValueBag<'v> {
345    fn from(v: &'v &'a [&'b str]) -> Self {
346        ValueBag::from_seq_slice(v)
347    }
348}
349
350impl<'v, 'a, 'b> From<Option<&'v &'a [&'b str]>> for ValueBag<'v> {
351    fn from(v: Option<&'v &'a [&'b str]>) -> Self {
352        ValueBag::from_option(v)
353    }
354}
355
356#[cfg(feature = "alloc")]
357impl<'v> From<&'v Vec<String>> for ValueBag<'v> {
358    fn from(v: &'v Vec<String>) -> Self {
359        ValueBag::from_seq_slice(v)
360    }
361}
362
363#[cfg(feature = "alloc")]
364impl<'v> From<Option<&'v Vec<String>>> for ValueBag<'v> {
365    fn from(v: Option<&'v Vec<String>>) -> Self {
366        ValueBag::from_option(v)
367    }
368}
369
370#[derive(Default)]
371pub(crate) struct ExtendPrimitive<S, T>(S, PhantomData<T>);
372
373impl<S, T> ExtendPrimitive<S, T> {
374    pub fn into_inner(self) -> S {
375        self.0
376    }
377}
378
379impl<'a, S: Extend<Option<T>>, T: for<'b> TryFrom<ValueBag<'b>>> ExtendValue<'a>
380    for ExtendPrimitive<S, T>
381{
382    fn extend(&mut self, inner: Internal) {
383        self.0.extend(Some(ValueBag { inner }.try_into().ok()))
384    }
385}
386
387#[allow(dead_code)]
388pub(crate) trait ExtendValue<'v> {
389    fn extend(&mut self, v: Internal);
390
391    fn extend_borrowed(&mut self, v: Internal<'v>) {
392        self.extend(v);
393    }
394}
395
396struct ExtendVisitor<S>(S);
397
398impl<'v, S: ExtendValue<'v>> Visitor<'v> for ExtendVisitor<S> {
399    fn element(&mut self, v: ValueBag) -> ControlFlow<()> {
400        self.0.extend(v.inner);
401        ControlFlow::Continue(())
402    }
403
404    fn borrowed_element(&mut self, v: ValueBag<'v>) -> ControlFlow<()> {
405        self.0.extend_borrowed(v.inner);
406        ControlFlow::Continue(())
407    }
408}
409
410impl<'v> Internal<'v> {
411    #[inline]
412    pub(crate) fn extend<S: Default + ExtendValue<'v>>(&self) -> Option<S> {
413        struct SeqVisitor<S>(Option<S>);
414
415        impl<'v, S: Default + ExtendValue<'v>> InternalVisitor<'v> for SeqVisitor<S> {
416            #[inline]
417            fn fill(&mut self, v: &dyn crate::fill::Fill) -> Result<(), Error> {
418                v.fill(Slot::new(self))
419            }
420
421            #[inline]
422            fn debug(&mut self, _: &dyn fmt::Debug) -> Result<(), Error> {
423                Ok(())
424            }
425
426            #[inline]
427            fn display(&mut self, _: &dyn fmt::Display) -> Result<(), Error> {
428                Ok(())
429            }
430
431            #[inline]
432            fn u64(&mut self, _: u64) -> Result<(), Error> {
433                Ok(())
434            }
435
436            #[inline]
437            fn i64(&mut self, _: i64) -> Result<(), Error> {
438                Ok(())
439            }
440
441            #[inline]
442            fn u128(&mut self, _: &u128) -> Result<(), Error> {
443                Ok(())
444            }
445
446            #[inline]
447            fn i128(&mut self, _: &i128) -> Result<(), Error> {
448                Ok(())
449            }
450
451            #[inline]
452            fn f64(&mut self, _: f64) -> Result<(), Error> {
453                Ok(())
454            }
455
456            #[inline]
457            fn bool(&mut self, _: bool) -> Result<(), Error> {
458                Ok(())
459            }
460
461            #[inline]
462            fn char(&mut self, _: char) -> Result<(), Error> {
463                Ok(())
464            }
465
466            #[inline]
467            fn str(&mut self, _: &str) -> Result<(), Error> {
468                Ok(())
469            }
470
471            #[inline]
472            fn none(&mut self) -> Result<(), Error> {
473                Ok(())
474            }
475
476            #[cfg(feature = "error")]
477            #[inline]
478            fn error(&mut self, _: &dyn crate::internal::error::Error) -> Result<(), Error> {
479                Ok(())
480            }
481
482            #[cfg(feature = "sval2")]
483            #[inline]
484            fn sval2(&mut self, v: &dyn crate::internal::sval::v2::Value) -> Result<(), Error> {
485                self.0 = crate::internal::sval::v2::seq::extend(v);
486
487                Ok(())
488            }
489
490            #[cfg(feature = "sval2")]
491            #[inline]
492            fn borrowed_sval2(
493                &mut self,
494                v: &'v dyn crate::internal::sval::v2::Value,
495            ) -> Result<(), Error> {
496                self.0 = crate::internal::sval::v2::seq::extend_borrowed(v);
497
498                Ok(())
499            }
500
501            #[cfg(feature = "serde1")]
502            #[inline]
503            fn serde1(
504                &mut self,
505                v: &dyn crate::internal::serde::v1::Serialize,
506            ) -> Result<(), Error> {
507                self.0 = crate::internal::serde::v1::seq::extend(v);
508
509                Ok(())
510            }
511
512            fn seq(&mut self, seq: &dyn Seq) -> Result<(), Error> {
513                let mut s = ExtendVisitor(S::default());
514                seq.visit(&mut s);
515                self.0 = Some(s.0);
516
517                Ok(())
518            }
519
520            fn borrowed_seq(&mut self, seq: &'v dyn Seq) -> Result<(), Error> {
521                let mut s = ExtendVisitor(S::default());
522                seq.borrowed_visit(&mut s);
523                self.0 = Some(s.0);
524
525                Ok(())
526            }
527
528            fn poisoned(&mut self, _: &'static str) -> Result<(), Error> {
529                Ok(())
530            }
531        }
532
533        let mut visitor = SeqVisitor(None);
534        let _ = self.internal_visit(&mut visitor);
535
536        visitor.0
537    }
538}
539
540#[cfg(feature = "alloc")]
541mod alloc_support {
542    use super::*;
543
544    use crate::std::borrow::Cow;
545
546    impl<'v> ValueBag<'v> {
547        /// Try get a collection `S` of strings from this value.
548        ///
549        /// If this value is a sequence then the collection `S` will be extended
550        /// with the attempted conversion of each of its elements.
551        ///
552        /// If this value is not a sequence then this method will return `None`.
553        #[inline]
554        pub fn to_str_seq<S: Default + Extend<Option<Cow<'v, str>>>>(&self) -> Option<S> {
555            #[derive(Default)]
556            struct ExtendStr<'a, S>(S, PhantomData<Cow<'a, str>>);
557
558            impl<'a, S: Extend<Option<Cow<'a, str>>>> ExtendValue<'a> for ExtendStr<'a, S> {
559                fn extend(&mut self, inner: Internal<'_>) {
560                    self.0.extend(Some(
561                        ValueBag { inner }
562                            .to_str()
563                            .map(|s| Cow::Owned(s.into_owned())),
564                    ))
565                }
566
567                fn extend_borrowed(&mut self, inner: Internal<'a>) {
568                    self.0.extend(Some(ValueBag { inner }.to_str()))
569                }
570            }
571
572            self.inner.extend::<ExtendStr<'v, S>>().map(|seq| seq.0)
573        }
574    }
575}
576
577#[cfg(feature = "owned")]
578pub(crate) mod owned {
579    use super::*;
580
581    use crate::{owned::OwnedValueBag, std::boxed::Box};
582
583    #[derive(Clone)]
584    pub(crate) struct OwnedSeq(Box<[OwnedValueBag]>);
585
586    impl Seq for OwnedSeq {
587        fn visit(&self, visitor: &mut dyn Visitor<'_>) {
588            for item in self.0.iter() {
589                if let ControlFlow::Break(()) = visitor.element(item.by_ref()) {
590                    return;
591                }
592            }
593        }
594    }
595
596    pub(crate) fn buffer(v: &dyn Seq) -> Result<OwnedSeq, Error> {
597        struct BufferVisitor(Vec<OwnedValueBag>);
598
599        impl<'v> Visitor<'v> for BufferVisitor {
600            fn element(&mut self, v: ValueBag) -> ControlFlow<()> {
601                self.0.push(v.to_owned());
602                ControlFlow::Continue(())
603            }
604        }
605
606        let mut buf = BufferVisitor(Vec::new());
607        v.visit(&mut buf);
608        Ok(OwnedSeq(buf.0.into_boxed_slice()))
609    }
610}
611
612#[cfg(test)]
613mod tests {
614    #[cfg(target_arch = "wasm32")]
615    use wasm_bindgen_test::*;
616
617    use std::vec::Vec;
618
619    use super::*;
620
621    #[test]
622    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
623    fn to_u64_seq() {
624        assert_eq!(
625            Some(vec![Some(1u64), Some(2u64), Some(3u64)]),
626            ValueBag::from(&[1u8, 2u8, 3u8]).to_u64_seq::<Vec<Option<u64>>>()
627        );
628
629        assert_eq!(
630            Some(vec![Some(1u64), Some(2u64), Some(3u64)]),
631            ValueBag::from(&[1u16, 2u16, 3u16]).to_u64_seq::<Vec<Option<u64>>>()
632        );
633
634        assert_eq!(
635            Some(vec![Some(1u64), Some(2u64), Some(3u64)]),
636            ValueBag::from(&[1u32, 2u32, 3u32]).to_u64_seq::<Vec<Option<u64>>>()
637        );
638
639        assert_eq!(
640            Some(vec![Some(1u64), Some(2u64), Some(3u64)]),
641            ValueBag::from(&[1u64, 2u64, 3u64]).to_u64_seq::<Vec<Option<u64>>>()
642        );
643    }
644
645    #[test]
646    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
647    fn to_i64_seq() {
648        assert_eq!(
649            Some(vec![Some(1i64), Some(2i64), Some(3i64)]),
650            ValueBag::from(&[1i8, 2i8, 3i8]).to_i64_seq::<Vec<Option<i64>>>()
651        );
652
653        assert_eq!(
654            Some(vec![Some(1i64), Some(2i64), Some(3i64)]),
655            ValueBag::from(&[1i16, 2i16, 3i16]).to_i64_seq::<Vec<Option<i64>>>()
656        );
657
658        assert_eq!(
659            Some(vec![Some(1i64), Some(2i64), Some(3i64)]),
660            ValueBag::from(&[1i32, 2i32, 3i32]).to_i64_seq::<Vec<Option<i64>>>()
661        );
662
663        assert_eq!(
664            Some(vec![Some(1i64), Some(2i64), Some(3i64)]),
665            ValueBag::from(&[1i64, 2i64, 3i64]).to_i64_seq::<Vec<Option<i64>>>()
666        );
667    }
668
669    #[test]
670    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
671    fn to_f64_seq() {
672        assert_eq!(
673            Some(vec![Some(1.0f64), Some(2.0f64), Some(3.0f64)]),
674            ValueBag::from(&[1.0f64, 2.0f64, 3.0f64]).to_f64_seq::<Vec<Option<f64>>>()
675        );
676    }
677
678    #[test]
679    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
680    fn as_f64_seq() {
681        assert_eq!(
682            Vec::<f64>::new(),
683            ValueBag::from(1.0f64).as_f64_seq::<Vec<f64>>()
684        );
685
686        assert_eq!(
687            vec![1.0f64, 2.0f64, 3.0f64],
688            ValueBag::from(&[1, 2, 3]).as_f64_seq::<Vec<f64>>()
689        );
690    }
691
692    #[test]
693    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
694    fn to_u128_seq() {
695        assert_eq!(
696            Some(vec![Some(1u128), Some(2u128), Some(3u128)]),
697            ValueBag::from(&[1u128, 2u128, 3u128]).to_u128_seq::<Vec<Option<u128>>>()
698        );
699    }
700
701    #[test]
702    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
703    fn to_i128_seq() {
704        assert_eq!(
705            Some(vec![Some(1i128), Some(2i128), Some(3i128)]),
706            ValueBag::from(&[1i128, 2i128, 3i128]).to_i128_seq::<Vec<Option<i128>>>()
707        );
708    }
709
710    #[test]
711    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
712    fn to_bool_seq() {
713        assert_eq!(
714            Some(vec![Some(true), Some(false)]),
715            ValueBag::from(&[true, false]).to_bool_seq::<Vec<Option<bool>>>()
716        );
717    }
718
719    #[test]
720    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
721    fn to_char_seq() {
722        assert_eq!(
723            Some(vec![Some('a'), Some('b'), Some('c')]),
724            ValueBag::from(&['a', 'b', 'c']).to_char_seq::<Vec<Option<char>>>()
725        );
726    }
727
728    #[test]
729    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
730    fn to_borrowed_str_seq() {
731        let v = ["a", "b", "c"];
732        let v = ValueBag::from(&v);
733
734        assert_eq!(
735            Some(vec![Some("a"), Some("b"), Some("c")]),
736            v.to_borrowed_str_seq::<Vec<Option<&str>>>()
737        );
738
739        let v = ValueBag::from_fill(&|slot: Slot| slot.fill_seq_slice(&["a", "b", "c"]));
740
741        assert_eq!(
742            Some(vec![None, None, None]),
743            v.to_borrowed_str_seq::<Vec<Option<&str>>>()
744        );
745    }
746
747    #[cfg(feature = "alloc")]
748    mod alloc_support {
749        use super::*;
750
751        use crate::std::borrow::Cow;
752
753        #[test]
754        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
755        fn to_str_seq() {
756            let v = ["a", "b", "c"];
757            let v = ValueBag::from(&v);
758
759            assert_eq!(
760                Some(vec![
761                    Some(Cow::Borrowed("a")),
762                    Some(Cow::Borrowed("b")),
763                    Some(Cow::Borrowed("c"))
764                ]),
765                v.to_str_seq::<Vec<Option<Cow<str>>>>()
766            );
767
768            let v = ValueBag::from_fill(&|slot: Slot| slot.fill_seq_slice(&["a", "b", "c"]));
769
770            assert_eq!(
771                Some(vec![
772                    Some(Cow::Owned("a".into())),
773                    Some(Cow::Owned("b".into())),
774                    Some(Cow::Owned("c".into()))
775                ]),
776                v.to_str_seq::<Vec<Option<Cow<str>>>>()
777            );
778        }
779    }
780}