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