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(
219 &mut self,
220 v: &(dyn crate::internal::error::Error + 'static),
221 ) -> Result<(), Error> {
222 Debug::fmt(v, self.0)?;
223
224 Ok(())
225 }
226
227 #[cfg(feature = "sval2")]
228 fn sval2(&mut self, v: &dyn crate::internal::sval::v2::Value) -> Result<(), Error> {
229 crate::internal::sval::v2::fmt(self.0, v)
230 }
231
232 #[cfg(feature = "serde1")]
233 fn serde1(
234 &mut self,
235 v: &dyn crate::internal::serde::v1::Serialize,
236 ) -> Result<(), Error> {
237 crate::internal::serde::v1::fmt(self.0, v)
238 }
239
240 #[cfg(feature = "seq")]
241 fn seq(&mut self, seq: &dyn crate::internal::seq::Seq) -> Result<(), Error> {
242 let mut visitor = seq::FmtSeq(self.0.debug_list());
243 seq.visit(&mut visitor);
244 visitor.0.finish()?;
245
246 Ok(())
247 }
248
249 fn poisoned(&mut self, msg: &'static str) -> Result<(), Error> {
250 write!(self.0, "<{msg}>")?;
251
252 Ok(())
253 }
254 }
255
256 self.internal_visit(&mut DebugVisitor(f))
257 .map_err(|_| fmt::Error)?;
258
259 Ok(())
260 }
261}
262
263impl<'v> Display for ValueBag<'v> {
264 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265 struct DisplayVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>);
266
267 impl<'a, 'b: 'a, 'v> InternalVisitor<'v> for DisplayVisitor<'a, 'b> {
268 fn fill(&mut self, v: &dyn crate::fill::Fill) -> Result<(), Error> {
269 v.fill(crate::fill::Slot::new(self))
270 }
271
272 fn debug(&mut self, v: &dyn Debug) -> Result<(), Error> {
273 Debug::fmt(v, self.0)?;
274
275 Ok(())
276 }
277
278 fn display(&mut self, v: &dyn Display) -> Result<(), Error> {
279 Display::fmt(v, self.0)?;
280
281 Ok(())
282 }
283
284 fn u64(&mut self, v: u64) -> Result<(), Error> {
285 Display::fmt(&v, self.0)?;
286
287 Ok(())
288 }
289
290 fn i64(&mut self, v: i64) -> Result<(), Error> {
291 Display::fmt(&v, self.0)?;
292
293 Ok(())
294 }
295
296 fn u128(&mut self, v: &u128) -> Result<(), Error> {
297 Display::fmt(&v, self.0)?;
298
299 Ok(())
300 }
301
302 fn i128(&mut self, v: &i128) -> Result<(), Error> {
303 Display::fmt(&v, self.0)?;
304
305 Ok(())
306 }
307
308 fn f64(&mut self, v: f64) -> Result<(), Error> {
309 Display::fmt(&v, self.0)?;
310
311 Ok(())
312 }
313
314 fn bool(&mut self, v: bool) -> Result<(), Error> {
315 Display::fmt(&v, self.0)?;
316
317 Ok(())
318 }
319
320 fn char(&mut self, v: char) -> Result<(), Error> {
321 Display::fmt(&v, self.0)?;
322
323 Ok(())
324 }
325
326 fn str(&mut self, v: &str) -> Result<(), Error> {
327 Display::fmt(&v, self.0)?;
328
329 Ok(())
330 }
331
332 fn none(&mut self) -> Result<(), Error> {
333 self.debug(&format_args!("None"))
334 }
335
336 #[cfg(feature = "error")]
337 fn error(
338 &mut self,
339 v: &(dyn crate::internal::error::Error + 'static),
340 ) -> Result<(), Error> {
341 Display::fmt(v, self.0)?;
342
343 Ok(())
344 }
345
346 #[cfg(feature = "sval2")]
347 fn sval2(&mut self, v: &dyn crate::internal::sval::v2::Value) -> Result<(), Error> {
348 crate::internal::sval::v2::fmt(self.0, v)
349 }
350
351 #[cfg(feature = "serde1")]
352 fn serde1(
353 &mut self,
354 v: &dyn crate::internal::serde::v1::Serialize,
355 ) -> Result<(), Error> {
356 crate::internal::serde::v1::fmt(self.0, v)
357 }
358
359 #[cfg(feature = "seq")]
360 fn seq(&mut self, seq: &dyn crate::internal::seq::Seq) -> Result<(), Error> {
361 let mut visitor = seq::FmtSeq(self.0.debug_list());
362 seq.visit(&mut visitor);
363 visitor.0.finish()?;
364
365 Ok(())
366 }
367
368 fn poisoned(&mut self, msg: &'static str) -> Result<(), Error> {
369 write!(self.0, "<{msg}>")?;
370
371 Ok(())
372 }
373 }
374
375 self.internal_visit(&mut DisplayVisitor(f))
376 .map_err(|_| fmt::Error)?;
377
378 Ok(())
379 }
380}
381
382#[cfg(feature = "seq")]
383mod seq {
384 use super::*;
385 use core::ops::ControlFlow;
386
387 pub(super) struct FmtSeq<'a, 'b>(pub(super) fmt::DebugList<'b, 'a>);
388
389 impl<'a, 'b, 'c> crate::internal::seq::Visitor<'c> for FmtSeq<'a, 'b> {
390 fn element(&mut self, inner: ValueBag) -> ControlFlow<()> {
391 self.0.entry(&inner);
392 ControlFlow::Continue(())
393 }
394 }
395}
396
397#[cfg(feature = "owned")]
398pub(crate) mod owned {
399 use crate::std::{boxed::Box, fmt};
400
401 #[cfg(feature = "inline-str")]
402 use crate::internal::owned::inline_str::{self, InlineStr};
403
404 impl fmt::Debug for crate::OwnedValueBag {
405 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406 fmt::Debug::fmt(&self.by_ref(), f)
407 }
408 }
409
410 impl fmt::Display for crate::OwnedValueBag {
411 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412 fmt::Display::fmt(&self.by_ref(), f)
413 }
414 }
415
416 #[cfg(not(feature = "inline-str"))]
417 pub(crate) enum InlineFmt {}
418
419 #[derive(Clone)]
420 pub(crate) struct OwnedFmt(Box<str>);
421
422 pub(crate) fn buffer_debug(v: impl fmt::Debug) -> Result<InlineFmt, OwnedFmt> {
423 #[cfg(feature = "inline-str")]
424 {
425 buffer_inline(format_args!("{v:?}"))
426 }
427 #[cfg(not(feature = "inline-str"))]
428 {
429 Err(OwnedFmt(format!("{v:?}").into()))
430 }
431 }
432
433 pub(crate) fn buffer_display(v: impl fmt::Display) -> Result<InlineFmt, OwnedFmt> {
434 #[cfg(feature = "inline-str")]
435 {
436 buffer_inline(v)
437 }
438 #[cfg(not(feature = "inline-str"))]
439 {
440 use crate::std::string::ToString as _;
441
442 Err(OwnedFmt(v.to_string().into()))
443 }
444 }
445
446 impl fmt::Debug for OwnedFmt {
447 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448 fmt::Display::fmt(self, f)
449 }
450 }
451
452 impl fmt::Display for OwnedFmt {
453 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
454 fmt::Display::fmt(&self.0, f)
455 }
456 }
457
458 #[cfg(feature = "inline-str")]
459 #[inline]
460 fn buffer_inline(v: impl fmt::Display) -> Result<InlineFmt, OwnedFmt> {
461 match InlineStr::<64>::buffer(v) {
464 Ok(inline) => {
465 if inline.len() <= inline_str::MAX_INLINE_LEN {
466 let inline = unsafe {
468 InlineStr::<{ inline_str::MAX_INLINE_LEN }>::copy_from_unchecked(
469 inline.get(),
470 )
471 };
472
473 Ok(InlineFmt(inline))
474 } else {
475 Err(OwnedFmt(Box::from(inline.get())))
476 }
477 }
478 Err(spilled) => Err(OwnedFmt(spilled)),
479 }
480 }
481
482 #[cfg(feature = "inline-str")]
483 #[derive(Clone, Copy)]
484 pub(crate) struct InlineFmt(InlineStr<{ inline_str::MAX_INLINE_LEN }>);
485
486 #[cfg(feature = "inline-str")]
487 impl fmt::Debug for InlineFmt {
488 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
489 fmt::Display::fmt(self, f)
490 }
491 }
492
493 #[cfg(feature = "inline-str")]
494 impl fmt::Display for InlineFmt {
495 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496 fmt::Display::fmt(&self.0, f)
497 }
498 }
499}
500
501impl<'v> From<&'v dyn Debug> for ValueBag<'v> {
502 #[inline]
503 fn from(v: &'v dyn Debug) -> Self {
504 ValueBag::from_dyn_debug(v)
505 }
506}
507
508impl<'v> From<Option<&'v dyn Debug>> for ValueBag<'v> {
509 #[inline]
510 fn from(v: Option<&'v dyn Debug>) -> Self {
511 ValueBag::from_option(v)
512 }
513}
514
515impl<'v, 'u> From<&'v &'u dyn Debug> for ValueBag<'v>
516where
517 'u: 'v,
518{
519 #[inline]
520 fn from(v: &'v &'u dyn Debug) -> Self {
521 ValueBag::from_dyn_debug(*v)
522 }
523}
524
525impl<'v> From<&'v dyn Display> for ValueBag<'v> {
526 #[inline]
527 fn from(v: &'v dyn Display) -> Self {
528 ValueBag::from_dyn_display(v)
529 }
530}
531
532impl<'v> From<Option<&'v dyn Display>> for ValueBag<'v> {
533 #[inline]
534 fn from(v: Option<&'v dyn Display>) -> Self {
535 ValueBag::from_option(v)
536 }
537}
538
539impl<'v, 'u> From<&'v &'u dyn Display> for ValueBag<'v>
540where
541 'u: 'v,
542{
543 #[inline]
544 fn from(v: &'v &'u dyn Display) -> Self {
545 ValueBag::from_dyn_display(*v)
546 }
547}
548
549#[cfg(test)]
550mod tests {
551 #[cfg(target_arch = "wasm32")]
552 use wasm_bindgen_test::*;
553
554 use super::*;
555 use crate::{
556 std::string::ToString,
557 test::{IntoValueBag, TestToken},
558 };
559
560 #[test]
561 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
562 fn fmt_capture() {
563 assert_eq!(
564 ValueBag::capture_debug(&1u16).to_test_token(),
565 TestToken::U64(1)
566 );
567 assert_eq!(
568 ValueBag::capture_display(&1u16).to_test_token(),
569 TestToken::U64(1)
570 );
571
572 assert_eq!(
573 ValueBag::capture_debug(&Some(1u16)).to_test_token(),
574 TestToken::U64(1)
575 );
576 }
577
578 #[test]
579 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
580 fn fmt_fill() {
581 assert_eq!(
582 ValueBag::from_fill(&|slot: Slot| slot.fill_debug(1u16)).to_test_token(),
583 TestToken::Str("1".into())
584 );
585 assert_eq!(
586 ValueBag::from_fill(&|slot: Slot| slot.fill_display(1u16)).to_test_token(),
587 TestToken::Str("1".into())
588 );
589 }
590
591 #[test]
592 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
593 fn fmt_capture_args() {
594 assert_eq!(
595 ValueBag::from_debug(&format_args!("a {}", "value")).to_string(),
596 "a value"
597 );
598 }
599
600 #[test]
601 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
602 fn fmt_cast() {
603 assert_eq!(
604 42u64,
605 ValueBag::capture_debug(&42u64)
606 .to_u64()
607 .expect("invalid value")
608 );
609
610 assert_eq!(
611 "a string",
612 ValueBag::capture_display(&"a string")
613 .to_borrowed_str()
614 .expect("invalid value")
615 );
616 }
617
618 #[test]
619 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
620 fn fmt_downcast() {
621 #[derive(Debug, PartialEq, Eq)]
622 struct Timestamp(usize);
623
624 impl Display for Timestamp {
625 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
626 write!(f, "time is {}", self.0)
627 }
628 }
629
630 let ts = Timestamp(42);
631
632 assert_eq!(
633 &ts,
634 ValueBag::capture_debug(&ts)
635 .downcast_ref::<Timestamp>()
636 .expect("invalid value")
637 );
638
639 assert_eq!(
640 &ts,
641 ValueBag::capture_display(&ts)
642 .downcast_ref::<Timestamp>()
643 .expect("invalid value")
644 );
645 }
646
647 #[test]
648 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
649 fn fmt_debug() {
650 assert_eq!(
651 format!("{:?}", "a string"),
652 format!("{:?}", "a string".into_value_bag().by_ref()),
653 );
654
655 assert_eq!(
656 format!("{:04?}", 42u64),
657 format!("{:04?}", 42u64.into_value_bag().by_ref()),
658 );
659 }
660
661 #[test]
662 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
663 fn fmt_display() {
664 assert_eq!(
665 format!("{}", "a string"),
666 format!("{}", "a string".into_value_bag().by_ref()),
667 );
668
669 assert_eq!(
670 format!("{:04}", 42u64),
671 format!("{:04}", 42u64.into_value_bag().by_ref()),
672 );
673 }
674
675 #[cfg(feature = "seq")]
676 mod seq_support {
677 use super::*;
678
679 #[test]
680 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
681 fn fmt_debug_seq() {
682 assert_eq!(
683 "[01, 02, 03]",
684 format!("{:>02?}", ValueBag::from_seq_slice(&[1, 2, 3]))
685 );
686 }
687
688 #[test]
689 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
690 fn fmt_display_seq() {
691 assert_eq!(
692 "[1, 2, 3]",
693 format!("{}", ValueBag::from_seq_slice(&[1, 2, 3]))
694 );
695 }
696 }
697}