fmt_tools/
fmt_fn.rs

1use core::fmt::{self, Debug, Display, Formatter};
2
3/// Implements [`Debug`] and [`Display`] based on a function object.
4pub struct FmtFn<F>
5where
6    F: ?Sized,
7{
8    values_fn: F,
9}
10
11impl<F> FmtFn<F> {
12    const fn new(values_fn: F) -> Self {
13        Self { values_fn }
14    }
15}
16
17impl<F> Display for FmtFn<F>
18where
19    F: Fn(&mut Formatter) -> fmt::Result + ?Sized,
20{
21    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
22        (self.values_fn)(f)
23    }
24}
25
26impl<F> Debug for FmtFn<F>
27where
28    F: Fn(&mut Formatter) -> fmt::Result + ?Sized,
29{
30    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
31        (self.values_fn)(f)
32    }
33}
34
35/// Creates an object that implements [`Debug`] and [`Display`] based on the provided function object.
36///
37/// Example:
38///
39/// ```rust
40/// let fmt = fmt_tools::fmt_fn(|f| f.write_str("foo"));
41///
42/// assert_eq!(format!("{fmt:?}"), "foo");
43/// assert_eq!(format!("{fmt}"), "foo");
44/// ```
45pub const fn fmt_fn<F>(f: F) -> FmtFn<F>
46where
47    F: Fn(&mut Formatter) -> fmt::Result,
48{
49    FmtFn::new(f)
50}
51
52#[cfg(test)]
53mod tests {
54    use super::FmtFn;
55    use core::fmt::{self, Formatter};
56
57    #[test]
58    fn test_fmt_fn() {
59        let fmt = super::fmt_fn(|f| f.write_str("foo"));
60
61        assert_eq!(std::format!("{fmt:?}"), "foo");
62        assert_eq!(std::format!("{fmt}"), "foo");
63    }
64
65    #[test]
66    fn test_coerce_unsized() {
67        let fmt: &FmtFn<dyn Fn(&mut Formatter) -> fmt::Result> = &super::fmt_fn(|f| f.write_str("foo"));
68
69        assert_eq!(std::format!("{fmt:?}"), "foo");
70        assert_eq!(std::format!("{fmt}"), "foo");
71    }
72}