value_bag/internal/
fmt.rs

1//! Integration between `Value` and `std::fmt`.
2//!
3//! This module allows any `Value` to implement the `Debug` and `Display` traits,
4//! and for any `Debug` or `Display` to be captured as a `Value`.
5
6use crate::{
7    fill::Slot,
8    std::{any::Any, fmt},
9    Error, ValueBag,
10};
11
12use super::{Internal, InternalVisitor};
13
14impl<'v> ValueBag<'v> {
15    /// Get a value from a debuggable type.
16    ///
17    /// This method will attempt to capture the given value as a well-known primitive
18    /// before resorting to using its `Debug` implementation.
19    pub fn capture_debug<T>(value: &'v T) -> Self
20    where
21        T: Debug + 'static,
22    {
23        Self::try_capture(value).unwrap_or(ValueBag {
24            inner: Internal::Debug(value),
25        })
26    }
27
28    /// Get a value from a displayable type.
29    ///
30    /// This method will attempt to capture the given value as a well-known primitive
31    /// before resorting to using its `Display` implementation.
32    pub fn capture_display<T>(value: &'v T) -> Self
33    where
34        T: Display + 'static,
35    {
36        Self::try_capture(value).unwrap_or(ValueBag {
37            inner: Internal::Display(value),
38        })
39    }
40
41    /// Get a value from a debuggable type without capturing support.
42    pub const fn from_debug<T>(value: &'v T) -> Self
43    where
44        T: Debug,
45    {
46        ValueBag {
47            inner: Internal::AnonDebug(value),
48        }
49    }
50
51    /// Get a value from a displayable type without capturing support.
52    pub const fn from_display<T>(value: &'v T) -> Self
53    where
54        T: Display,
55    {
56        ValueBag {
57            inner: Internal::AnonDisplay(value),
58        }
59    }
60
61    /// Get a value from a debuggable type without capturing support.
62    #[inline]
63    pub const fn from_dyn_debug(value: &'v dyn Debug) -> Self {
64        ValueBag {
65            inner: Internal::AnonDebug(value),
66        }
67    }
68
69    /// Get a value from a displayable type without capturing support.
70    #[inline]
71    pub const fn from_dyn_display(value: &'v dyn Display) -> Self {
72        ValueBag {
73            inner: Internal::AnonDisplay(value),
74        }
75    }
76}
77
78pub(crate) trait DowncastDisplay {
79    fn as_any(&self) -> &dyn Any;
80    fn as_super(&self) -> &dyn fmt::Display;
81}
82
83impl<T: fmt::Display + 'static> DowncastDisplay for T {
84    fn as_any(&self) -> &dyn Any {
85        self
86    }
87
88    fn as_super(&self) -> &dyn fmt::Display {
89        self
90    }
91}
92
93impl<'a> fmt::Display for dyn DowncastDisplay + Send + Sync + 'a {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        self.as_super().fmt(f)
96    }
97}
98
99pub(crate) trait DowncastDebug {
100    fn as_any(&self) -> &dyn Any;
101    fn as_super(&self) -> &dyn fmt::Debug;
102}
103
104impl<T: fmt::Debug + 'static> DowncastDebug for T {
105    fn as_any(&self) -> &dyn Any {
106        self
107    }
108
109    fn as_super(&self) -> &dyn fmt::Debug {
110        self
111    }
112}
113
114impl<'a> fmt::Debug for dyn DowncastDebug + Send + Sync + 'a {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        self.as_super().fmt(f)
117    }
118}
119
120impl<'s, 'f> Slot<'s, 'f> {
121    /// Fill the slot with a debuggable value.
122    ///
123    /// The given value doesn't need to satisfy any particular lifetime constraints.
124    pub fn fill_debug<T>(self, value: T) -> Result<(), Error>
125    where
126        T: Debug,
127    {
128        self.fill(|visitor| visitor.debug(&value))
129    }
130
131    /// Fill the slot with a displayable value.
132    ///
133    /// The given value doesn't need to satisfy any particular lifetime constraints.
134    pub fn fill_display<T>(self, value: T) -> Result<(), Error>
135    where
136        T: Display,
137    {
138        self.fill(|visitor| visitor.display(&value))
139    }
140}
141
142pub use self::fmt::{Debug, Display};
143
144impl<'v> Debug for ValueBag<'v> {
145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146        struct DebugVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>);
147
148        impl<'a, 'b: 'a, 'v> InternalVisitor<'v> for DebugVisitor<'a, 'b> {
149            fn fill(&mut self, v: &dyn crate::fill::Fill) -> Result<(), Error> {
150                v.fill(crate::fill::Slot::new(self))
151            }
152
153            fn debug(&mut self, v: &dyn Debug) -> Result<(), Error> {
154                Debug::fmt(v, self.0)?;
155
156                Ok(())
157            }
158
159            fn display(&mut self, v: &dyn Display) -> Result<(), Error> {
160                Display::fmt(v, self.0)?;
161
162                Ok(())
163            }
164
165            fn u64(&mut self, v: u64) -> Result<(), Error> {
166                Debug::fmt(&v, self.0)?;
167
168                Ok(())
169            }
170
171            fn i64(&mut self, v: i64) -> Result<(), Error> {
172                Debug::fmt(&v, self.0)?;
173
174                Ok(())
175            }
176
177            fn u128(&mut self, v: &u128) -> Result<(), Error> {
178                Debug::fmt(&v, self.0)?;
179
180                Ok(())
181            }
182
183            fn i128(&mut self, v: &i128) -> Result<(), Error> {
184                Debug::fmt(&v, self.0)?;
185
186                Ok(())
187            }
188
189            fn f64(&mut self, v: f64) -> Result<(), Error> {
190                Debug::fmt(&v, self.0)?;
191
192                Ok(())
193            }
194
195            fn bool(&mut self, v: bool) -> Result<(), Error> {
196                Debug::fmt(&v, self.0)?;
197
198                Ok(())
199            }
200
201            fn char(&mut self, v: char) -> Result<(), Error> {
202                Debug::fmt(&v, self.0)?;
203
204                Ok(())
205            }
206
207            fn str(&mut self, v: &str) -> Result<(), Error> {
208                Debug::fmt(&v, self.0)?;
209
210                Ok(())
211            }
212
213            fn none(&mut self) -> Result<(), Error> {
214                self.debug(&format_args!("None"))
215            }
216
217            #[cfg(feature = "error")]
218            fn error(&mut self, v: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
219                Debug::fmt(v, self.0)?;
220
221                Ok(())
222            }
223
224            #[cfg(feature = "sval2")]
225            fn sval2(&mut self, v: &dyn crate::internal::sval::v2::Value) -> Result<(), Error> {
226                crate::internal::sval::v2::fmt(self.0, v)
227            }
228
229            #[cfg(feature = "serde1")]
230            fn serde1(
231                &mut self,
232                v: &dyn crate::internal::serde::v1::Serialize,
233            ) -> Result<(), Error> {
234                crate::internal::serde::v1::fmt(self.0, v)
235            }
236
237            #[cfg(feature = "seq")]
238            fn seq(&mut self, seq: &dyn crate::internal::seq::Seq) -> Result<(), Error> {
239                let mut visitor = seq::FmtSeq(self.0.debug_list());
240                seq.visit(&mut visitor);
241                visitor.0.finish()?;
242
243                Ok(())
244            }
245
246            fn poisoned(&mut self, msg: &'static str) -> Result<(), Error> {
247                write!(self.0, "<{msg}>")?;
248
249                Ok(())
250            }
251        }
252
253        self.internal_visit(&mut DebugVisitor(f))
254            .map_err(|_| fmt::Error)?;
255
256        Ok(())
257    }
258}
259
260impl<'v> Display for ValueBag<'v> {
261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262        struct DisplayVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>);
263
264        impl<'a, 'b: 'a, 'v> InternalVisitor<'v> for DisplayVisitor<'a, 'b> {
265            fn fill(&mut self, v: &dyn crate::fill::Fill) -> Result<(), Error> {
266                v.fill(crate::fill::Slot::new(self))
267            }
268
269            fn debug(&mut self, v: &dyn Debug) -> Result<(), Error> {
270                Debug::fmt(v, self.0)?;
271
272                Ok(())
273            }
274
275            fn display(&mut self, v: &dyn Display) -> Result<(), Error> {
276                Display::fmt(v, self.0)?;
277
278                Ok(())
279            }
280
281            fn u64(&mut self, v: u64) -> Result<(), Error> {
282                Display::fmt(&v, self.0)?;
283
284                Ok(())
285            }
286
287            fn i64(&mut self, v: i64) -> Result<(), Error> {
288                Display::fmt(&v, self.0)?;
289
290                Ok(())
291            }
292
293            fn u128(&mut self, v: &u128) -> Result<(), Error> {
294                Display::fmt(&v, self.0)?;
295
296                Ok(())
297            }
298
299            fn i128(&mut self, v: &i128) -> Result<(), Error> {
300                Display::fmt(&v, self.0)?;
301
302                Ok(())
303            }
304
305            fn f64(&mut self, v: f64) -> Result<(), Error> {
306                Display::fmt(&v, self.0)?;
307
308                Ok(())
309            }
310
311            fn bool(&mut self, v: bool) -> Result<(), Error> {
312                Display::fmt(&v, self.0)?;
313
314                Ok(())
315            }
316
317            fn char(&mut self, v: char) -> Result<(), Error> {
318                Display::fmt(&v, self.0)?;
319
320                Ok(())
321            }
322
323            fn str(&mut self, v: &str) -> Result<(), Error> {
324                Display::fmt(&v, self.0)?;
325
326                Ok(())
327            }
328
329            fn none(&mut self) -> Result<(), Error> {
330                self.debug(&format_args!("None"))
331            }
332
333            #[cfg(feature = "error")]
334            fn error(&mut self, v: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
335                Display::fmt(v, self.0)?;
336
337                Ok(())
338            }
339
340            #[cfg(feature = "sval2")]
341            fn sval2(&mut self, v: &dyn crate::internal::sval::v2::Value) -> Result<(), Error> {
342                crate::internal::sval::v2::fmt(self.0, v)
343            }
344
345            #[cfg(feature = "serde1")]
346            fn serde1(
347                &mut self,
348                v: &dyn crate::internal::serde::v1::Serialize,
349            ) -> Result<(), Error> {
350                crate::internal::serde::v1::fmt(self.0, v)
351            }
352
353            #[cfg(feature = "seq")]
354            fn seq(&mut self, seq: &dyn crate::internal::seq::Seq) -> Result<(), Error> {
355                let mut visitor = seq::FmtSeq(self.0.debug_list());
356                seq.visit(&mut visitor);
357                visitor.0.finish()?;
358
359                Ok(())
360            }
361
362            fn poisoned(&mut self, msg: &'static str) -> Result<(), Error> {
363                write!(self.0, "<{msg}>")?;
364
365                Ok(())
366            }
367        }
368
369        self.internal_visit(&mut DisplayVisitor(f))
370            .map_err(|_| fmt::Error)?;
371
372        Ok(())
373    }
374}
375
376#[cfg(feature = "seq")]
377mod seq {
378    use super::*;
379    use core::ops::ControlFlow;
380
381    pub(super) struct FmtSeq<'a, 'b>(pub(super) fmt::DebugList<'b, 'a>);
382
383    impl<'a, 'b, 'c> crate::internal::seq::Visitor<'c> for FmtSeq<'a, 'b> {
384        fn element(&mut self, inner: ValueBag) -> ControlFlow<()> {
385            self.0.entry(&inner);
386            ControlFlow::Continue(())
387        }
388    }
389}
390
391#[cfg(feature = "owned")]
392pub(crate) mod owned {
393    use crate::std::{boxed::Box, fmt, string::ToString};
394
395    impl fmt::Debug for crate::OwnedValueBag {
396        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
397            fmt::Debug::fmt(&self.by_ref(), f)
398        }
399    }
400
401    impl fmt::Display for crate::OwnedValueBag {
402        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403            fmt::Display::fmt(&self.by_ref(), f)
404        }
405    }
406
407    #[derive(Clone)]
408    pub(crate) struct OwnedFmt(Box<str>);
409
410    pub(crate) fn buffer_debug(v: impl fmt::Debug) -> OwnedFmt {
411        OwnedFmt(format!("{:?}", v).into())
412    }
413
414    pub(crate) fn buffer_display(v: impl fmt::Display) -> OwnedFmt {
415        OwnedFmt(v.to_string().into())
416    }
417
418    impl fmt::Debug for OwnedFmt {
419        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
420            fmt::Display::fmt(self, f)
421        }
422    }
423
424    impl fmt::Display for OwnedFmt {
425        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426            fmt::Display::fmt(&self.0, f)
427        }
428    }
429}
430
431impl<'v> From<&'v dyn Debug> for ValueBag<'v> {
432    #[inline]
433    fn from(v: &'v dyn Debug) -> Self {
434        ValueBag::from_dyn_debug(v)
435    }
436}
437
438impl<'v> From<Option<&'v dyn Debug>> for ValueBag<'v> {
439    #[inline]
440    fn from(v: Option<&'v dyn Debug>) -> Self {
441        ValueBag::from_option(v)
442    }
443}
444
445impl<'v, 'u> From<&'v &'u dyn Debug> for ValueBag<'v>
446where
447    'u: 'v,
448{
449    #[inline]
450    fn from(v: &'v &'u dyn Debug) -> Self {
451        ValueBag::from_dyn_debug(*v)
452    }
453}
454
455impl<'v> From<&'v dyn Display> for ValueBag<'v> {
456    #[inline]
457    fn from(v: &'v dyn Display) -> Self {
458        ValueBag::from_dyn_display(v)
459    }
460}
461
462impl<'v> From<Option<&'v dyn Display>> for ValueBag<'v> {
463    #[inline]
464    fn from(v: Option<&'v dyn Display>) -> Self {
465        ValueBag::from_option(v)
466    }
467}
468
469impl<'v, 'u> From<&'v &'u dyn Display> for ValueBag<'v>
470where
471    'u: 'v,
472{
473    #[inline]
474    fn from(v: &'v &'u dyn Display) -> Self {
475        ValueBag::from_dyn_display(*v)
476    }
477}
478
479#[cfg(test)]
480mod tests {
481    #[cfg(target_arch = "wasm32")]
482    use wasm_bindgen_test::*;
483
484    use super::*;
485    use crate::{
486        std::string::ToString,
487        test::{IntoValueBag, TestToken},
488    };
489
490    #[test]
491    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
492    fn fmt_capture() {
493        assert_eq!(
494            ValueBag::capture_debug(&1u16).to_test_token(),
495            TestToken::U64(1)
496        );
497        assert_eq!(
498            ValueBag::capture_display(&1u16).to_test_token(),
499            TestToken::U64(1)
500        );
501
502        assert_eq!(
503            ValueBag::capture_debug(&Some(1u16)).to_test_token(),
504            TestToken::U64(1)
505        );
506    }
507
508    #[test]
509    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
510    fn fmt_fill() {
511        assert_eq!(
512            ValueBag::from_fill(&|slot: Slot| slot.fill_debug(1u16)).to_test_token(),
513            TestToken::Str("1".into())
514        );
515        assert_eq!(
516            ValueBag::from_fill(&|slot: Slot| slot.fill_display(1u16)).to_test_token(),
517            TestToken::Str("1".into())
518        );
519    }
520
521    #[test]
522    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
523    fn fmt_capture_args() {
524        assert_eq!(
525            ValueBag::from_debug(&format_args!("a {}", "value")).to_string(),
526            "a value"
527        );
528    }
529
530    #[test]
531    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
532    fn fmt_cast() {
533        assert_eq!(
534            42u64,
535            ValueBag::capture_debug(&42u64)
536                .to_u64()
537                .expect("invalid value")
538        );
539
540        assert_eq!(
541            "a string",
542            ValueBag::capture_display(&"a string")
543                .to_borrowed_str()
544                .expect("invalid value")
545        );
546    }
547
548    #[test]
549    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
550    fn fmt_downcast() {
551        #[derive(Debug, PartialEq, Eq)]
552        struct Timestamp(usize);
553
554        impl Display for Timestamp {
555            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
556                write!(f, "time is {}", self.0)
557            }
558        }
559
560        let ts = Timestamp(42);
561
562        assert_eq!(
563            &ts,
564            ValueBag::capture_debug(&ts)
565                .downcast_ref::<Timestamp>()
566                .expect("invalid value")
567        );
568
569        assert_eq!(
570            &ts,
571            ValueBag::capture_display(&ts)
572                .downcast_ref::<Timestamp>()
573                .expect("invalid value")
574        );
575    }
576
577    #[test]
578    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
579    fn fmt_debug() {
580        assert_eq!(
581            format!("{:?}", "a string"),
582            format!("{:?}", "a string".into_value_bag().by_ref()),
583        );
584
585        assert_eq!(
586            format!("{:04?}", 42u64),
587            format!("{:04?}", 42u64.into_value_bag().by_ref()),
588        );
589    }
590
591    #[test]
592    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
593    fn fmt_display() {
594        assert_eq!(
595            format!("{}", "a string"),
596            format!("{}", "a string".into_value_bag().by_ref()),
597        );
598
599        assert_eq!(
600            format!("{:04}", 42u64),
601            format!("{:04}", 42u64.into_value_bag().by_ref()),
602        );
603    }
604
605    #[cfg(feature = "seq")]
606    mod seq_support {
607        use super::*;
608
609        #[test]
610        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
611        fn fmt_debug_seq() {
612            assert_eq!(
613                "[01, 02, 03]",
614                format!("{:>02?}", ValueBag::from_seq_slice(&[1, 2, 3]))
615            );
616        }
617
618        #[test]
619        #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
620        fn fmt_display_seq() {
621            assert_eq!(
622                "[1, 2, 3]",
623                format!("{}", ValueBag::from_seq_slice(&[1, 2, 3]))
624            );
625        }
626    }
627}