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, 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}