1use crate::{
7 fill::Slot,
8 std::{any::Any, fmt},
9 Error, ValueBag,
10};
11
12use super::{Internal, InternalVisitor};
13
14impl<'v> ValueBag<'v> {
15 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 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 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 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 #[inline]
63 pub const fn from_dyn_debug(value: &'v dyn Debug) -> Self {
64 ValueBag {
65 inner: Internal::AnonDebug(value),
66 }
67 }
68
69 #[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 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 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};
394
395 #[cfg(feature = "inline-str")]
396 use crate::internal::owned::inline_str::{self, InlineStr};
397
398 impl fmt::Debug for crate::OwnedValueBag {
399 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
400 fmt::Debug::fmt(&self.by_ref(), f)
401 }
402 }
403
404 impl fmt::Display for crate::OwnedValueBag {
405 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406 fmt::Display::fmt(&self.by_ref(), f)
407 }
408 }
409
410 #[cfg(not(feature = "inline-str"))]
411 pub(crate) enum InlineFmt {}
412
413 #[derive(Clone)]
414 pub(crate) struct OwnedFmt(Box<str>);
415
416 pub(crate) fn buffer_debug(v: impl fmt::Debug) -> Result<InlineFmt, OwnedFmt> {
417 #[cfg(feature = "inline-str")]
418 {
419 buffer_inline(format_args!("{v:?}"))
420 }
421 #[cfg(not(feature = "inline-str"))]
422 {
423 Err(OwnedFmt(format!("{v:?}").into()))
424 }
425 }
426
427 pub(crate) fn buffer_display(v: impl fmt::Display) -> Result<InlineFmt, OwnedFmt> {
428 #[cfg(feature = "inline-str")]
429 {
430 buffer_inline(v)
431 }
432 #[cfg(not(feature = "inline-str"))]
433 {
434 use crate::std::string::ToString as _;
435
436 Err(OwnedFmt(v.to_string().into()))
437 }
438 }
439
440 impl fmt::Debug for OwnedFmt {
441 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
442 fmt::Display::fmt(self, f)
443 }
444 }
445
446 impl fmt::Display for OwnedFmt {
447 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448 fmt::Display::fmt(&self.0, f)
449 }
450 }
451
452 #[cfg(feature = "inline-str")]
453 #[inline]
454 fn buffer_inline(v: impl fmt::Display) -> Result<InlineFmt, OwnedFmt> {
455 match InlineStr::<64>::buffer(v) {
458 Ok(inline) => {
459 if inline.len() <= inline_str::MAX_INLINE_LEN {
460 let inline = unsafe {
462 InlineStr::<{ inline_str::MAX_INLINE_LEN }>::copy_from_unchecked(
463 inline.get(),
464 )
465 };
466
467 Ok(InlineFmt(inline))
468 } else {
469 Err(OwnedFmt(Box::from(inline.get())))
470 }
471 }
472 Err(spilled) => Err(OwnedFmt(spilled)),
473 }
474 }
475
476 #[cfg(feature = "inline-str")]
477 #[derive(Clone, Copy)]
478 pub(crate) struct InlineFmt(InlineStr<{ inline_str::MAX_INLINE_LEN }>);
479
480 #[cfg(feature = "inline-str")]
481 impl fmt::Debug for InlineFmt {
482 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483 fmt::Display::fmt(self, f)
484 }
485 }
486
487 #[cfg(feature = "inline-str")]
488 impl fmt::Display for InlineFmt {
489 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
490 fmt::Display::fmt(&self.0, f)
491 }
492 }
493}
494
495impl<'v> From<&'v dyn Debug> for ValueBag<'v> {
496 #[inline]
497 fn from(v: &'v dyn Debug) -> Self {
498 ValueBag::from_dyn_debug(v)
499 }
500}
501
502impl<'v> From<Option<&'v dyn Debug>> for ValueBag<'v> {
503 #[inline]
504 fn from(v: Option<&'v dyn Debug>) -> Self {
505 ValueBag::from_option(v)
506 }
507}
508
509impl<'v, 'u> From<&'v &'u dyn Debug> for ValueBag<'v>
510where
511 'u: 'v,
512{
513 #[inline]
514 fn from(v: &'v &'u dyn Debug) -> Self {
515 ValueBag::from_dyn_debug(*v)
516 }
517}
518
519impl<'v> From<&'v dyn Display> for ValueBag<'v> {
520 #[inline]
521 fn from(v: &'v dyn Display) -> Self {
522 ValueBag::from_dyn_display(v)
523 }
524}
525
526impl<'v> From<Option<&'v dyn Display>> for ValueBag<'v> {
527 #[inline]
528 fn from(v: Option<&'v dyn Display>) -> Self {
529 ValueBag::from_option(v)
530 }
531}
532
533impl<'v, 'u> From<&'v &'u dyn Display> for ValueBag<'v>
534where
535 'u: 'v,
536{
537 #[inline]
538 fn from(v: &'v &'u dyn Display) -> Self {
539 ValueBag::from_dyn_display(*v)
540 }
541}
542
543#[cfg(test)]
544mod tests {
545 #[cfg(target_arch = "wasm32")]
546 use wasm_bindgen_test::*;
547
548 use super::*;
549 use crate::{
550 std::string::ToString,
551 test::{IntoValueBag, TestToken},
552 };
553
554 #[test]
555 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
556 fn fmt_capture() {
557 assert_eq!(
558 ValueBag::capture_debug(&1u16).to_test_token(),
559 TestToken::U64(1)
560 );
561 assert_eq!(
562 ValueBag::capture_display(&1u16).to_test_token(),
563 TestToken::U64(1)
564 );
565
566 assert_eq!(
567 ValueBag::capture_debug(&Some(1u16)).to_test_token(),
568 TestToken::U64(1)
569 );
570 }
571
572 #[test]
573 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
574 fn fmt_fill() {
575 assert_eq!(
576 ValueBag::from_fill(&|slot: Slot| slot.fill_debug(1u16)).to_test_token(),
577 TestToken::Str("1".into())
578 );
579 assert_eq!(
580 ValueBag::from_fill(&|slot: Slot| slot.fill_display(1u16)).to_test_token(),
581 TestToken::Str("1".into())
582 );
583 }
584
585 #[test]
586 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
587 fn fmt_capture_args() {
588 assert_eq!(
589 ValueBag::from_debug(&format_args!("a {}", "value")).to_string(),
590 "a value"
591 );
592 }
593
594 #[test]
595 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
596 fn fmt_cast() {
597 assert_eq!(
598 42u64,
599 ValueBag::capture_debug(&42u64)
600 .to_u64()
601 .expect("invalid value")
602 );
603
604 assert_eq!(
605 "a string",
606 ValueBag::capture_display(&"a string")
607 .to_borrowed_str()
608 .expect("invalid value")
609 );
610 }
611
612 #[test]
613 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
614 fn fmt_downcast() {
615 #[derive(Debug, PartialEq, Eq)]
616 struct Timestamp(usize);
617
618 impl Display for Timestamp {
619 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
620 write!(f, "time is {}", self.0)
621 }
622 }
623
624 let ts = Timestamp(42);
625
626 assert_eq!(
627 &ts,
628 ValueBag::capture_debug(&ts)
629 .downcast_ref::<Timestamp>()
630 .expect("invalid value")
631 );
632
633 assert_eq!(
634 &ts,
635 ValueBag::capture_display(&ts)
636 .downcast_ref::<Timestamp>()
637 .expect("invalid value")
638 );
639 }
640
641 #[test]
642 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
643 fn fmt_debug() {
644 assert_eq!(
645 format!("{:?}", "a string"),
646 format!("{:?}", "a string".into_value_bag().by_ref()),
647 );
648
649 assert_eq!(
650 format!("{:04?}", 42u64),
651 format!("{:04?}", 42u64.into_value_bag().by_ref()),
652 );
653 }
654
655 #[test]
656 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
657 fn fmt_display() {
658 assert_eq!(
659 format!("{}", "a string"),
660 format!("{}", "a string".into_value_bag().by_ref()),
661 );
662
663 assert_eq!(
664 format!("{:04}", 42u64),
665 format!("{:04}", 42u64.into_value_bag().by_ref()),
666 );
667 }
668
669 #[cfg(feature = "seq")]
670 mod seq_support {
671 use super::*;
672
673 #[test]
674 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
675 fn fmt_debug_seq() {
676 assert_eq!(
677 "[01, 02, 03]",
678 format!("{:>02?}", ValueBag::from_seq_slice(&[1, 2, 3]))
679 );
680 }
681
682 #[test]
683 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
684 fn fmt_display_seq() {
685 assert_eq!(
686 "[1, 2, 3]",
687 format!("{}", ValueBag::from_seq_slice(&[1, 2, 3]))
688 );
689 }
690 }
691}