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}