value_bag/internal/sval/
v2.rs

1//! Integration between `Value` and `sval`.
2//!
3//! This module allows any `Value` to implement the `Value` trait,
4//! and for any `Value` to be captured as a `Value`.
5
6use crate::{
7    fill::Slot,
8    internal::{Internal, InternalVisitor},
9    std::{any::Any, fmt},
10    Error, ValueBag,
11};
12
13impl<'v> ValueBag<'v> {
14    /// Get a value from a structured type.
15    ///
16    /// This method will attempt to capture the given value as a well-known primitive
17    /// before resorting to using its `Value` implementation.
18    pub fn capture_sval2<T>(value: &'v T) -> Self
19    where
20        T: value_bag_sval2::lib::Value + 'static,
21    {
22        Self::try_capture(value).unwrap_or(ValueBag {
23            inner: Internal::Sval2(value),
24        })
25    }
26
27    /// Get a value from a structured type without capturing support.
28    pub const fn from_sval2<T>(value: &'v T) -> Self
29    where
30        T: value_bag_sval2::lib::Value,
31    {
32        ValueBag {
33            inner: Internal::AnonSval2(value),
34        }
35    }
36
37    /// Get a value from a structured type without capturing support.
38    #[inline]
39    pub const fn from_dyn_sval2(value: &'v dyn Value) -> Self {
40        ValueBag {
41            inner: Internal::AnonSval2(value),
42        }
43    }
44}
45
46pub(crate) trait DowncastValue {
47    fn as_any(&self) -> &dyn Any;
48    fn as_super(&self) -> &dyn Value;
49}
50
51impl<T: value_bag_sval2::lib::Value + 'static> DowncastValue for T {
52    fn as_any(&self) -> &dyn Any {
53        self
54    }
55
56    fn as_super(&self) -> &dyn Value {
57        self
58    }
59}
60
61impl<'s, 'f> Slot<'s, 'f> {
62    /// Fill the slot with a structured value.
63    ///
64    /// The given value doesn't need to satisfy any particular lifetime constraints.
65    pub fn fill_sval2<T>(self, value: T) -> Result<(), Error>
66    where
67        T: value_bag_sval2::lib::Value,
68    {
69        self.fill(|visitor| visitor.sval2(&value))
70    }
71}
72
73impl<'v> value_bag_sval2::lib::Value for ValueBag<'v> {
74    fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
75        &'sval self,
76        s: &mut S,
77    ) -> value_bag_sval2::lib::Result {
78        use value_bag_sval2::lib_ref::ValueRef as _;
79
80        self.stream_ref(s)
81    }
82}
83
84impl<'sval> value_bag_sval2::lib_ref::ValueRef<'sval> for ValueBag<'sval> {
85    fn stream_ref<S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
86        &self,
87        s: &mut S,
88    ) -> value_bag_sval2::lib::Result {
89        struct Sval2Visitor<'a, S: ?Sized>(&'a mut S);
90
91        impl<'a, 'v, S: value_bag_sval2::lib::Stream<'v> + ?Sized> InternalVisitor<'v>
92            for Sval2Visitor<'a, S>
93        {
94            fn fill(&mut self, v: &dyn crate::fill::Fill) -> Result<(), Error> {
95                v.fill(crate::fill::Slot::new(self))
96            }
97
98            fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> {
99                value_bag_sval2::fmt::stream_debug(self.0, v).map_err(Error::from_sval2)
100            }
101
102            fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> {
103                value_bag_sval2::fmt::stream_display(self.0, v).map_err(Error::from_sval2)
104            }
105
106            fn u64(&mut self, v: u64) -> Result<(), Error> {
107                self.0.u64(v).map_err(Error::from_sval2)
108            }
109
110            fn i64(&mut self, v: i64) -> Result<(), Error> {
111                self.0.i64(v).map_err(Error::from_sval2)
112            }
113
114            fn u128(&mut self, v: &u128) -> Result<(), Error> {
115                self.0.u128(*v).map_err(Error::from_sval2)
116            }
117
118            fn i128(&mut self, v: &i128) -> Result<(), Error> {
119                self.0.i128(*v).map_err(Error::from_sval2)
120            }
121
122            fn f64(&mut self, v: f64) -> Result<(), Error> {
123                self.0.f64(v).map_err(Error::from_sval2)
124            }
125
126            fn bool(&mut self, v: bool) -> Result<(), Error> {
127                self.0.bool(v).map_err(Error::from_sval2)
128            }
129
130            fn char(&mut self, v: char) -> Result<(), Error> {
131                let mut buf = [0; 4];
132                let v = v.encode_utf8(&mut buf);
133
134                self.0.value_computed(v).map_err(Error::from_sval2)
135            }
136
137            fn str(&mut self, v: &str) -> Result<(), Error> {
138                self.0.value_computed(v).map_err(Error::from_sval2)
139            }
140
141            fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> {
142                self.0.value(v).map_err(Error::from_sval2)
143            }
144
145            fn none(&mut self) -> Result<(), Error> {
146                self.0.null().map_err(Error::from_sval2)
147            }
148
149            #[cfg(feature = "error")]
150            fn error(&mut self, v: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
151                self.display(&v)
152            }
153
154            fn sval2(&mut self, v: &dyn Value) -> Result<(), Error> {
155                self.0.value_computed(v).map_err(Error::from_sval2)
156            }
157
158            fn borrowed_sval2(&mut self, v: &'v dyn Value) -> Result<(), Error> {
159                self.0.value(v).map_err(Error::from_sval2)
160            }
161
162            #[cfg(feature = "serde1")]
163            fn serde1(
164                &mut self,
165                v: &dyn crate::internal::serde::v1::Serialize,
166            ) -> Result<(), Error> {
167                crate::internal::serde::v1::sval2(self.0, v)
168            }
169
170            #[cfg(feature = "seq")]
171            fn seq(&mut self, v: &dyn crate::internal::seq::Seq) -> Result<(), Error> {
172                self.0.seq_begin(None).map_err(Error::from_sval2)?;
173
174                let mut s = seq::StreamVisitor {
175                    stream: &mut *self.0,
176                    err: None,
177                };
178                v.visit(&mut s);
179                if let Some(e) = s.err {
180                    return Err(Error::from_sval2(e));
181                }
182
183                self.0.seq_end().map_err(Error::from_sval2)
184            }
185
186            #[cfg(feature = "seq")]
187            fn borrowed_seq(&mut self, v: &'v dyn crate::internal::seq::Seq) -> Result<(), Error> {
188                self.0.seq_begin(None).map_err(Error::from_sval2)?;
189
190                let mut s = seq::StreamVisitor {
191                    stream: &mut *self.0,
192                    err: None,
193                };
194                v.borrowed_visit(&mut s);
195                if let Some(e) = s.err {
196                    return Err(Error::from_sval2(e));
197                }
198
199                self.0.seq_end().map_err(Error::from_sval2)
200            }
201
202            fn poisoned(&mut self, msg: &'static str) -> Result<(), Error> {
203                Err(Error::msg(msg))
204            }
205        }
206
207        self.internal_visit(&mut Sval2Visitor(s))
208            .map_err(Error::into_sval2)?;
209
210        Ok(())
211    }
212}
213
214pub use value_bag_sval2::dynamic::Value;
215
216pub(in crate::internal) fn fmt(f: &mut fmt::Formatter, v: &dyn Value) -> Result<(), Error> {
217    value_bag_sval2::fmt::stream_to_fmt(f, v)?;
218    Ok(())
219}
220
221#[cfg(feature = "serde1")]
222pub(in crate::internal) fn serde1<S>(s: S, v: &dyn Value) -> Result<S::Ok, S::Error>
223where
224    S: value_bag_serde1::lib::Serializer,
225{
226    value_bag_sval2::serde1::serialize(s, v)
227}
228
229pub(crate) fn internal_visit(v: &dyn Value, visitor: &mut dyn InternalVisitor<'_>) -> bool {
230    let mut visitor = VisitorStream {
231        visitor,
232        text_buf: Default::default(),
233    };
234
235    value_bag_sval2::lib::stream_computed(&mut visitor, v).is_ok()
236}
237
238pub(crate) fn borrowed_internal_visit<'v>(
239    v: &'v dyn Value,
240    visitor: &mut dyn InternalVisitor<'v>,
241) -> bool {
242    let mut visitor = VisitorStream {
243        visitor,
244        text_buf: Default::default(),
245    };
246
247    value_bag_sval2::lib::stream(&mut visitor, v).is_ok()
248}
249
250struct VisitorStream<'a, 'v> {
251    visitor: &'a mut dyn InternalVisitor<'v>,
252    text_buf: value_bag_sval2::buffer::TextBuf<'v>,
253}
254
255impl<'a, 'v> value_bag_sval2::lib::Stream<'v> for VisitorStream<'a, 'v> {
256    fn null(&mut self) -> value_bag_sval2::lib::Result {
257        self.visitor.none().map_err(Error::into_sval2)
258    }
259
260    fn bool(&mut self, v: bool) -> value_bag_sval2::lib::Result {
261        self.visitor.bool(v).map_err(Error::into_sval2)
262    }
263
264    fn i64(&mut self, v: i64) -> value_bag_sval2::lib::Result {
265        self.visitor.i64(v).map_err(Error::into_sval2)
266    }
267
268    fn u64(&mut self, v: u64) -> value_bag_sval2::lib::Result {
269        self.visitor.u64(v).map_err(Error::into_sval2)
270    }
271
272    fn i128(&mut self, v: i128) -> value_bag_sval2::lib::Result {
273        self.visitor.i128(&v).map_err(Error::into_sval2)
274    }
275
276    fn u128(&mut self, v: u128) -> value_bag_sval2::lib::Result {
277        self.visitor.u128(&v).map_err(Error::into_sval2)
278    }
279
280    fn f64(&mut self, v: f64) -> value_bag_sval2::lib::Result {
281        self.visitor.f64(v).map_err(Error::into_sval2)
282    }
283
284    fn text_begin(&mut self, _: Option<usize>) -> value_bag_sval2::lib::Result {
285        self.text_buf.clear();
286        Ok(())
287    }
288
289    fn text_fragment_computed(&mut self, f: &str) -> value_bag_sval2::lib::Result {
290        self.text_buf
291            .push_fragment_computed(f)
292            .map_err(|_| value_bag_sval2::lib::Error::new())
293    }
294
295    fn text_fragment(&mut self, f: &'v str) -> value_bag_sval2::lib::Result {
296        self.text_buf
297            .push_fragment(f)
298            .map_err(|_| value_bag_sval2::lib::Error::new())
299    }
300
301    fn text_end(&mut self) -> value_bag_sval2::lib::Result {
302        if let Some(v) = self.text_buf.as_borrowed_str() {
303            self.visitor.borrowed_str(v).map_err(Error::into_sval2)
304        } else {
305            self.visitor
306                .str(self.text_buf.as_str())
307                .map_err(Error::into_sval2)
308        }
309    }
310
311    fn seq_begin(&mut self, _: Option<usize>) -> value_bag_sval2::lib::Result {
312        value_bag_sval2::lib::error()
313    }
314
315    fn seq_value_begin(&mut self) -> value_bag_sval2::lib::Result {
316        value_bag_sval2::lib::error()
317    }
318
319    fn seq_value_end(&mut self) -> value_bag_sval2::lib::Result {
320        value_bag_sval2::lib::error()
321    }
322
323    fn seq_end(&mut self) -> value_bag_sval2::lib::Result {
324        value_bag_sval2::lib::error()
325    }
326}
327
328impl Error {
329    pub(in crate::internal) fn from_sval2(_: value_bag_sval2::lib::Error) -> Self {
330        Error::msg("`sval` serialization failed")
331    }
332
333    pub(in crate::internal) fn into_sval2(self) -> value_bag_sval2::lib::Error {
334        value_bag_sval2::lib::Error::new()
335    }
336}
337
338#[cfg(feature = "seq")]
339pub(crate) mod seq {
340    use super::*;
341
342    use crate::{
343        internal::seq::{ExtendValue, Visitor},
344        std::ops::ControlFlow,
345    };
346
347    pub(super) struct StreamVisitor<'a, S: ?Sized> {
348        pub(super) stream: &'a mut S,
349        pub(super) err: Option<value_bag_sval2::lib::Error>,
350    }
351
352    impl<'a, 'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized> Visitor<'sval>
353        for StreamVisitor<'a, S>
354    {
355        fn element(&mut self, v: ValueBag) -> ControlFlow<()> {
356            if let Err(e) = self.stream.seq_value_begin() {
357                self.err = Some(e);
358                return ControlFlow::Break(());
359            }
360
361            if let Err(e) = value_bag_sval2::lib::stream_computed(&mut *self.stream, v) {
362                self.err = Some(e);
363                return ControlFlow::Break(());
364            }
365
366            if let Err(e) = self.stream.seq_value_end() {
367                self.err = Some(e);
368                return ControlFlow::Break(());
369            }
370
371            ControlFlow::Continue(())
372        }
373
374        fn borrowed_element(&mut self, v: ValueBag<'sval>) -> ControlFlow<()> {
375            if let Err(e) = self.stream.seq_value_begin() {
376                self.err = Some(e);
377                return ControlFlow::Break(());
378            }
379
380            if let Err(e) = value_bag_sval2::lib_ref::stream_ref(&mut *self.stream, v) {
381                self.err = Some(e);
382                return ControlFlow::Break(());
383            }
384
385            if let Err(e) = self.stream.seq_value_end() {
386                self.err = Some(e);
387                return ControlFlow::Break(());
388            }
389
390            ControlFlow::Continue(())
391        }
392    }
393
394    #[inline]
395    pub(crate) fn extend<'a, 'b, S: Default + ExtendValue<'a>>(v: &'b dyn Value) -> Option<S> {
396        let mut stream = Root {
397            seq: None,
398            text_buf: Default::default(),
399            depth: 0,
400        };
401
402        value_bag_sval2::lib::stream_computed(&mut stream, v).ok()?;
403
404        stream.seq
405    }
406
407    #[inline]
408    pub(crate) fn extend_borrowed<'a, S: Default + ExtendValue<'a>>(v: &'a dyn Value) -> Option<S> {
409        let mut stream = Root {
410            seq: None,
411            text_buf: Default::default(),
412            depth: 0,
413        };
414
415        value_bag_sval2::lib::stream(&mut stream, v).ok()?;
416
417        stream.seq
418    }
419
420    struct Root<'v, S> {
421        seq: Option<S>,
422        text_buf: value_bag_sval2::buffer::TextBuf<'v>,
423        depth: usize,
424    }
425
426    fn extend_borrowed_internal<'sval>(
427        seq: Option<&mut impl ExtendValue<'sval>>,
428        depth: usize,
429        v: impl Into<ValueBag<'sval>>,
430    ) -> value_bag_sval2::lib::Result {
431        if depth != 1 {
432            return Ok(());
433        }
434
435        if let Some(seq) = seq {
436            seq.extend_borrowed(v.into().inner);
437
438            Ok(())
439        } else {
440            value_bag_sval2::lib::error()
441        }
442    }
443
444    fn extend_internal<'a, 'sval>(
445        seq: Option<&mut impl ExtendValue<'sval>>,
446        depth: usize,
447        v: impl Into<ValueBag<'a>>,
448    ) -> value_bag_sval2::lib::Result {
449        if depth != 1 {
450            return Ok(());
451        }
452
453        if let Some(seq) = seq {
454            seq.extend(v.into().inner);
455
456            Ok(())
457        } else {
458            value_bag_sval2::lib::error()
459        }
460    }
461
462    impl<'sval, S: Default + ExtendValue<'sval>> value_bag_sval2::lib::Stream<'sval>
463        for Root<'sval, S>
464    {
465        fn null(&mut self) -> value_bag_sval2::lib::Result {
466            extend_borrowed_internal(self.seq.as_mut(), self.depth, ())
467        }
468
469        fn bool(&mut self, v: bool) -> value_bag_sval2::lib::Result {
470            extend_borrowed_internal(self.seq.as_mut(), self.depth, v)
471        }
472
473        fn i64(&mut self, v: i64) -> value_bag_sval2::lib::Result {
474            extend_borrowed_internal(self.seq.as_mut(), self.depth, v)
475        }
476
477        fn u64(&mut self, v: u64) -> value_bag_sval2::lib::Result {
478            extend_borrowed_internal(self.seq.as_mut(), self.depth, v)
479        }
480
481        fn i128(&mut self, v: i128) -> value_bag_sval2::lib::Result {
482            #[cfg(feature = "inline-i128")]
483            {
484                extend_borrowed_internal(self.seq.as_mut(), self.depth, v)
485            }
486            #[cfg(not(feature = "inline-i128"))]
487            {
488                extend_internal(self.seq.as_mut(), self.depth, &v)
489            }
490        }
491
492        fn u128(&mut self, v: u128) -> value_bag_sval2::lib::Result {
493            #[cfg(feature = "inline-i128")]
494            {
495                extend_borrowed_internal(self.seq.as_mut(), self.depth, v)
496            }
497            #[cfg(not(feature = "inline-i128"))]
498            {
499                extend_internal(self.seq.as_mut(), self.depth, &v)
500            }
501        }
502
503        fn f64(&mut self, v: f64) -> value_bag_sval2::lib::Result {
504            extend_borrowed_internal(self.seq.as_mut(), self.depth, v)
505        }
506
507        fn text_begin(&mut self, _: Option<usize>) -> value_bag_sval2::lib::Result {
508            self.text_buf.clear();
509            Ok(())
510        }
511
512        fn text_fragment_computed(&mut self, f: &str) -> value_bag_sval2::lib::Result {
513            self.text_buf
514                .push_fragment_computed(f)
515                .map_err(|_| value_bag_sval2::lib::Error::new())
516        }
517
518        fn text_fragment(&mut self, f: &'sval str) -> value_bag_sval2::lib::Result {
519            self.text_buf
520                .push_fragment(f)
521                .map_err(|_| value_bag_sval2::lib::Error::new())
522        }
523
524        fn text_end(&mut self) -> value_bag_sval2::lib::Result {
525            if let Some(v) = self.text_buf.as_borrowed_str() {
526                extend_borrowed_internal(self.seq.as_mut(), self.depth, v)
527            } else {
528                let v = self.text_buf.as_str();
529                extend_internal(self.seq.as_mut(), self.depth, v)
530            }
531        }
532
533        fn seq_begin(&mut self, _: Option<usize>) -> value_bag_sval2::lib::Result {
534            if self.seq.is_none() {
535                self.seq = Some(S::default());
536            }
537
538            self.depth += 1;
539
540            // Treat nested complex values as null
541            // This ensures an upstream visitor sees them, but won't
542            // be able to convert them into anything meaningful
543            if self.depth > 1 {
544                if let Some(ref mut seq) = self.seq {
545                    seq.extend_borrowed(ValueBag::from(()).inner);
546                }
547            }
548
549            Ok(())
550        }
551
552        fn seq_value_begin(&mut self) -> value_bag_sval2::lib::Result {
553            Ok(())
554        }
555
556        fn seq_value_end(&mut self) -> value_bag_sval2::lib::Result {
557            Ok(())
558        }
559
560        fn seq_end(&mut self) -> value_bag_sval2::lib::Result {
561            self.depth -= 1;
562
563            Ok(())
564        }
565    }
566}
567
568#[cfg(feature = "owned")]
569pub(crate) mod owned {
570    impl value_bag_sval2::lib::Value for crate::OwnedValueBag {
571        fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
572            &'sval self,
573            s: &mut S,
574        ) -> value_bag_sval2::lib::Result {
575            value_bag_sval2::lib_ref::ValueRef::stream_ref(&self.by_ref(), s)
576        }
577    }
578
579    pub(crate) type OwnedValue = value_bag_sval2::buffer::Value<'static>;
580
581    pub(crate) fn buffer(
582        v: impl value_bag_sval2::lib::Value,
583    ) -> Result<OwnedValue, value_bag_sval2::buffer::Error> {
584        OwnedValue::collect_owned(v)
585    }
586}
587
588impl<'v> From<&'v dyn Value> for ValueBag<'v> {
589    #[inline]
590    fn from(v: &'v dyn Value) -> Self {
591        ValueBag::from_dyn_sval2(v)
592    }
593}
594
595impl<'v> From<Option<&'v dyn Value>> for ValueBag<'v> {
596    #[inline]
597    fn from(v: Option<&'v dyn Value>) -> Self {
598        ValueBag::from_option(v)
599    }
600}
601
602impl<'v, 'u> From<&'v &'u dyn Value> for ValueBag<'v>
603where
604    'u: 'v,
605{
606    #[inline]
607    fn from(v: &'v &'u dyn Value) -> Self {
608        ValueBag::from_dyn_sval2(*v)
609    }
610}
611
612#[cfg(test)]
613mod tests {
614    #[cfg(target_arch = "wasm32")]
615    use wasm_bindgen_test::*;
616
617    use super::*;
618    use crate::test::*;
619
620    #[test]
621    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
622    fn sval2_capture() {
623        assert_eq!(
624            ValueBag::capture_sval2(&42u64).to_test_token(),
625            TestToken::U64(42)
626        );
627    }
628
629    #[test]
630    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
631    fn sval2_fill() {
632        assert_eq!(
633            ValueBag::from_fill(&|slot: Slot| slot.fill_sval2(42u64)).to_test_token(),
634            TestToken::Sval { version: 2 },
635        );
636    }
637
638    #[test]
639    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
640    fn sval2_capture_cast() {
641        assert_eq!(
642            42u64,
643            ValueBag::capture_sval2(&42u64)
644                .to_u64()
645                .expect("invalid value")
646        );
647
648        assert_eq!(
649            "a string",
650            ValueBag::capture_sval2(&"a string")
651                .to_borrowed_str()
652                .expect("invalid value")
653        );
654
655        #[cfg(feature = "std")]
656        assert_eq!(
657            "a string",
658            ValueBag::capture_sval2(&"a string")
659                .to_str()
660                .expect("invalid value")
661        );
662    }
663
664    #[test]
665    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
666    fn sval2_capture_cast_borrowed_str() {
667        struct Number<'a>(&'a str);
668
669        impl<'a> value_bag_sval2::lib::Value for Number<'a> {
670            fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
671                &'sval self,
672                stream: &mut S,
673            ) -> value_bag_sval2::lib::Result {
674                stream.tagged_begin(Some(&value_bag_sval2::lib::tags::NUMBER), None, None)?;
675                stream.value(self.0)?;
676                stream.tagged_end(Some(&value_bag_sval2::lib::tags::NUMBER), None, None)
677            }
678        }
679
680        assert_eq!(
681            "123.456e789",
682            ValueBag::capture_sval2(&Number("123.456e789"))
683                .to_borrowed_str()
684                .expect("invalid value")
685        );
686    }
687
688    #[test]
689    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
690    fn sval2_from_cast() {
691        assert_eq!(
692            42u64,
693            ValueBag::from_sval2(&42u64)
694                .to_u64()
695                .expect("invalid value")
696        );
697
698        #[cfg(feature = "std")]
699        assert_eq!(
700            "a string",
701            ValueBag::from_sval2(&"a string")
702                .to_str()
703                .expect("invalid value")
704        );
705    }
706
707    #[test]
708    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
709    fn sval2_downcast() {
710        #[derive(Debug, PartialEq, Eq)]
711        struct Timestamp(usize);
712
713        impl value_bag_sval2::lib::Value for Timestamp {
714            fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
715                &'sval self,
716                stream: &mut S,
717            ) -> value_bag_sval2::lib::Result {
718                stream.u64(self.0 as u64)
719            }
720        }
721
722        let ts = Timestamp(42);
723
724        assert_eq!(
725            &ts,
726            ValueBag::capture_sval2(&ts)
727                .downcast_ref::<Timestamp>()
728                .expect("invalid value")
729        );
730    }
731
732    #[test]
733    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
734    fn sval2_structured() {
735        let value = ValueBag::from(42u64);
736
737        value_bag_sval2::test::assert_tokens(&value, &[value_bag_sval2::test::Token::U64(42)]);
738    }
739
740    #[test]
741    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
742    fn sval2_debug() {
743        struct TestSval;
744
745        impl value_bag_sval2::lib::Value for TestSval {
746            fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
747                &'sval self,
748                stream: &mut S,
749            ) -> value_bag_sval2::lib::Result {
750                stream.u64(42)
751            }
752        }
753
754        assert_eq!(
755            format!("{:04?}", 42u64),
756            format!("{:04?}", ValueBag::capture_sval2(&TestSval)),
757        );
758    }
759
760    #[test]
761    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
762    fn sval2_visit() {
763        ValueBag::from_sval2(&42u64)
764            .visit(TestVisit::default())
765            .expect("failed to visit value");
766        ValueBag::from_sval2(&-42i64)
767            .visit(TestVisit::default())
768            .expect("failed to visit value");
769        ValueBag::from_sval2(&11f64)
770            .visit(TestVisit::default())
771            .expect("failed to visit value");
772        ValueBag::from_sval2(&true)
773            .visit(TestVisit::default())
774            .expect("failed to visit value");
775        ValueBag::from_sval2(&"some borrowed string")
776            .visit(TestVisit::default())
777            .expect("failed to visit value");
778        ValueBag::from_sval2(&'n')
779            .visit(TestVisit {
780                str: "n",
781                ..Default::default()
782            })
783            .expect("failed to visit value");
784    }
785
786    #[test]
787    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
788    #[cfg(feature = "serde1")]
789    fn sval2_serde1() {
790        use value_bag_serde1::test::{assert_ser_tokens, Token};
791
792        struct TestSval;
793
794        impl value_bag_sval2::lib::Value for TestSval {
795            fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
796                &'sval self,
797                stream: &mut S,
798            ) -> value_bag_sval2::lib::Result {
799                stream.u64(42)
800            }
801        }
802
803        assert_ser_tokens(&ValueBag::capture_sval2(&TestSval), &[Token::U64(42)]);
804    }
805
806    #[cfg(feature = "seq")]
807    mod seq_support {
808        use super::*;
809
810        use crate::std::vec::Vec;
811
812        #[test]
813        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
814        fn sval2_stream_borrowed_str_seq() {
815            let value = ValueBag::from_seq_slice(&["a", "b", "c"]);
816
817            value_bag_sval2::test::assert_tokens(&value, {
818                use value_bag_sval2::test::Token::*;
819
820                &[
821                    SeqBegin(None),
822                    SeqValueBegin,
823                    TextBegin(Some(1)),
824                    TextFragment("a"),
825                    TextEnd,
826                    SeqValueEnd,
827                    SeqValueBegin,
828                    TextBegin(Some(1)),
829                    TextFragment("b"),
830                    TextEnd,
831                    SeqValueEnd,
832                    SeqValueBegin,
833                    TextBegin(Some(1)),
834                    TextFragment("c"),
835                    TextEnd,
836                    SeqValueEnd,
837                    SeqEnd,
838                ]
839            });
840        }
841
842        #[test]
843        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
844        fn sval2_stream_str_seq() {
845            let value = ValueBag::from_fill(&|slot: Slot| slot.fill_seq_slice(&["a", "b", "c"]));
846
847            value_bag_sval2::test::assert_tokens(&value, {
848                use value_bag_sval2::test::Token::*;
849
850                &[
851                    SeqBegin(None),
852                    SeqValueBegin,
853                    TextBegin(Some(1)),
854                    TextFragmentComputed("a".into()),
855                    TextEnd,
856                    SeqValueEnd,
857                    SeqValueBegin,
858                    TextBegin(Some(1)),
859                    TextFragmentComputed("b".into()),
860                    TextEnd,
861                    SeqValueEnd,
862                    SeqValueBegin,
863                    TextBegin(Some(1)),
864                    TextFragmentComputed("c".into()),
865                    TextEnd,
866                    SeqValueEnd,
867                    SeqEnd,
868                ]
869            });
870        }
871
872        #[test]
873        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
874        #[cfg(feature = "alloc")]
875        fn sval2_borrowed_str_to_seq() {
876            use crate::std::borrow::Cow;
877
878            assert_eq!(
879                vec![
880                    Some(Cow::Borrowed("a string 1")),
881                    Some(Cow::Borrowed("a string 2")),
882                    Some(Cow::Borrowed("a string 3"))
883                ],
884                ValueBag::capture_sval2(&[&"a string 1", &"a string 2", &"a string 3",])
885                    .to_str_seq::<Vec<Option<Cow<str>>>>()
886                    .expect("invalid value")
887            );
888        }
889
890        #[test]
891        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
892        fn sval2_to_seq() {
893            assert_eq!(
894                vec![Some(1.0), None, None, Some(2.0), Some(3.0), None],
895                ValueBag::capture_sval2(&[
896                    &1.0 as &dyn Value,
897                    &true as &dyn Value,
898                    &[1.0, 2.0, 3.0] as &dyn Value,
899                    &2.0 as &dyn Value,
900                    &3.0 as &dyn Value,
901                    &"a string" as &dyn Value,
902                ])
903                .to_f64_seq::<Vec<Option<f64>>>()
904                .expect("invalid value")
905            );
906        }
907
908        #[test]
909        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
910        fn sval2_as_seq() {
911            assert_eq!(
912                vec![1.0, 2.0, 3.0],
913                ValueBag::capture_sval2(&[1.0, 2.0, 3.0,]).as_f64_seq::<Vec<f64>>()
914            );
915        }
916    }
917
918    #[cfg(feature = "std")]
919    mod std_support {
920        use super::*;
921
922        use crate::std::borrow::ToOwned;
923
924        #[test]
925        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
926        fn sval2_cast() {
927            assert_eq!(
928                "a string",
929                ValueBag::capture_sval2(&"a string".to_owned())
930                    .by_ref()
931                    .to_str()
932                    .expect("invalid value")
933            );
934        }
935    }
936
937    #[cfg(feature = "owned")]
938    mod owned_support {
939        use super::*;
940
941        #[test]
942        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
943        fn sval2_to_owned_poison() {
944            struct Kaboom;
945
946            impl value_bag_sval2::lib::Value for Kaboom {
947                fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
948                    &'sval self,
949                    _: &mut S,
950                ) -> value_bag_sval2::lib::Result {
951                    value_bag_sval2::lib::error()
952                }
953            }
954
955            let value = ValueBag::capture_sval2(&Kaboom)
956                .to_owned()
957                .by_ref()
958                .to_test_token();
959
960            assert_eq!(
961                TestToken::Poisoned("failed to buffer the value".into()),
962                value
963            );
964        }
965    }
966}