Skip to main content

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