Skip to main content

context_trait/
display_ctx.rs

1//! [`DisplayContext`]: custom display formatting via function pointer.
2
3use crate::WithContext;
4use std::fmt;
5
6/// A context providing a custom display function.
7///
8/// When used with [`WithContext`], implements `Display` by dispatching
9/// through the stored format function.
10///
11/// # Examples
12///
13/// ```
14/// use context_trait::{WithContext, DisplayContext};
15///
16/// let ctx = DisplayContext {
17///     display: |v: &(i32, i32), f: &mut std::fmt::Formatter| {
18///         write!(f, "({}, {})", v.0, v.1)
19///     },
20/// };
21/// let w = WithContext { inner: (1, 2), ctx };
22/// assert_eq!(format!("{w}"), "(1, 2)");
23/// ```
24pub struct DisplayContext<T> {
25    /// The display function.
26    pub display: fn(&T, &mut fmt::Formatter) -> fmt::Result,
27}
28
29impl<T> Clone for DisplayContext<T> {
30    fn clone(&self) -> Self {
31        *self
32    }
33}
34impl<T> Copy for DisplayContext<T> {}
35impl<T> std::fmt::Debug for DisplayContext<T> {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        f.debug_struct("DisplayContext")
38            .field("display", &(self.display as usize))
39            .finish()
40    }
41}
42
43impl<T> fmt::Display for WithContext<T, DisplayContext<T>> {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        (self.ctx.display)(&self.inner, f)
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn custom_display() {
55        let ctx = DisplayContext {
56            display: |v: &i32, f: &mut fmt::Formatter| write!(f, "value={v}"),
57        };
58        let w = WithContext { inner: 42, ctx };
59        assert_eq!(format!("{w}"), "value=42");
60    }
61
62    #[test]
63    fn display_struct() {
64        struct Point {
65            x: f64,
66            y: f64,
67        }
68
69        let ctx = DisplayContext {
70            display: |p: &Point, f: &mut fmt::Formatter| write!(f, "({}, {})", p.x, p.y),
71        };
72        let w = WithContext {
73            inner: Point { x: 1.5, y: 2.5 },
74            ctx,
75        };
76        assert_eq!(format!("{w}"), "(1.5, 2.5)");
77    }
78}