custom_format/runtime.rs
1//! Provides types associated to runtime formatting.
2
3use core::fmt;
4
5/// Trait for custom formatting with runtime format checking
6pub trait CustomFormat {
7 /// Formats the value using the given formatter.
8 ///
9 /// # Examples
10 ///
11 /// ```rust
12 /// use custom_format as cfmt;
13 ///
14 /// use core::fmt;
15 ///
16 /// #[derive(Debug)]
17 /// struct Hex(u8);
18 ///
19 /// impl cfmt::runtime::CustomFormat for Hex {
20 /// fn fmt(&self, f: &mut fmt::Formatter, spec: &str) -> fmt::Result {
21 /// match spec {
22 /// "x" => write!(f, "{:#02x}", self.0),
23 /// "X" => write!(f, "{:#02X}", self.0),
24 /// _ => Err(fmt::Error),
25 /// }
26 /// }
27 /// }
28 ///
29 /// // The custom format specifier is interpreted as a runtime specifier when it is inside "<>"
30 /// assert_eq!(cfmt::format!("{0:X?}, {0 :<x>}, {0 :<X>}", Hex(0xAB)), "Hex(AB), 0xab, 0xAB");
31 /// ```
32 ///
33 /// The following statement panics at runtime since `"z"` is not a valid format specifier:
34 ///
35 /// ```rust,should_panic
36 /// # use custom_format as cfmt;
37 /// # use core::fmt;
38 /// # struct Hex(u8);
39 /// # impl cfmt::runtime::CustomFormat for Hex {
40 /// # fn fmt(&self, f: &mut fmt::Formatter, spec: &str) -> fmt::Result {
41 /// # match spec {
42 /// # "x" => write!(f, "{:#02x}", self.0),
43 /// # "X" => write!(f, "{:#02X}", self.0),
44 /// # _ => Err(fmt::Error),
45 /// # }
46 /// # }
47 /// # }
48 /// cfmt::println!("{ :<z>}", Hex(0));
49 /// ```
50 ///
51 fn fmt(&self, f: &mut fmt::Formatter, spec: &str) -> fmt::Result;
52}
53
54/// Wrapper for custom formatting via its [`Display`](core::fmt::Display) trait
55#[derive(Debug, Clone)]
56pub struct CustomFormatter<'a, T> {
57 /// Format specifier
58 spec: &'static str,
59 /// Value to format
60 value: &'a T,
61}
62
63impl<'a, T> CustomFormatter<'a, T> {
64 /// Construct a new [`CustomFormatter`] value
65 pub fn new(spec: &'static str, value: &'a T) -> Self {
66 Self { spec, value }
67 }
68}
69
70impl<T: CustomFormat> fmt::Display for CustomFormatter<'_, T> {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 CustomFormat::fmt(self.value, f, self.spec)
73 }
74}