unwind_context/
func.rs

1use core::fmt::{Debug, Formatter, Result as FmtResult};
2
3use crate::{AnsiColorScheme, AnsiColored, DebugAnsiColored, UnwindContextArgs};
4
5/// A structure representing function name and its argument names and values.
6///
7/// This type is not intended to be used directly. Consider using macros like
8/// [`build_unwind_context_data`] or [`unwind_context`] instead.
9///
10/// [`build_unwind_context_data`]: crate::build_unwind_context_data
11/// [`unwind_context`]: crate::unwind_context
12#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
13pub struct UnwindContextFunc<Args> {
14    /// Function name.
15    pub name: &'static str,
16    /// Function argument names and values.
17    pub args: Args,
18}
19
20impl<Args> UnwindContextFunc<Args> {
21    /// Create a new `UnwindContextFunc` with the provided name and arguments.
22    ///
23    /// # Examples
24    ///
25    /// ```rust
26    /// use unwind_context::{UnwindContextArg, UnwindContextFunc};
27    ///
28    /// let func1 = UnwindContextFunc::new("name1", ());
29    ///
30    /// let func2 = UnwindContextFunc::new("name2", (UnwindContextArg::new(Some("first"), 123), ()));
31    ///
32    /// let func3 = UnwindContextFunc::new(
33    ///     "name3",
34    ///     (
35    ///         UnwindContextArg::new(Some("first"), 123),
36    ///         (
37    ///             UnwindContextArg::new(Some("second"), "foo"),
38    ///             (UnwindContextArg::new(Some("third"), true), ()),
39    ///         ),
40    ///     ),
41    /// );
42    /// ```
43    #[inline]
44    pub fn new(name: &'static str, args: Args) -> Self {
45        Self { name, args }
46    }
47}
48
49impl<Args> Debug for UnwindContextFunc<Args>
50where
51    for<'a> UnwindContextArgs<&'a Args>: Debug,
52{
53    #[inline]
54    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
55        write!(
56            f,
57            "fn {}({:?})",
58            self.name,
59            UnwindContextArgs::new(&self.args)
60        )?;
61        Ok(())
62    }
63}
64
65impl<Args> DebugAnsiColored for UnwindContextFunc<Args>
66where
67    for<'a> UnwindContextArgs<&'a Args>: DebugAnsiColored,
68{
69    #[inline]
70    fn fmt_colored(
71        &self,
72        f: &mut Formatter<'_>,
73        color_scheme: &'static AnsiColorScheme,
74    ) -> FmtResult {
75        write!(
76            f,
77            "{}fn {}{}{}({}{:?}{}){}",
78            color_scheme.fn_keyword,
79            color_scheme.func_name,
80            self.name,
81            color_scheme.func_braces,
82            color_scheme.default,
83            AnsiColored::new(UnwindContextArgs::new(&self.args), color_scheme),
84            color_scheme.func_braces,
85            color_scheme.default,
86        )?;
87        Ok(())
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use core::fmt::Error as FmtError;
94
95    use crate::test_common::{arg, TEST_COLOR_SCHEME};
96    use crate::test_util::debug_fmt;
97    use crate::{AnsiColored, UnwindContextFunc};
98
99    #[test]
100    fn test_func_fmt() {
101        let mut buffer = [0; 64];
102
103        assert_eq!(
104            debug_fmt(&mut buffer, &UnwindContextFunc::new("foo", ())),
105            Ok("fn foo()")
106        );
107        assert_eq!(
108            debug_fmt(
109                &mut buffer,
110                &UnwindContextFunc::new("foo", (arg(Some("bar"), 1), ()))
111            ),
112            Ok("fn foo(bar: 1)")
113        );
114        assert_eq!(
115            debug_fmt(
116                &mut buffer,
117                &UnwindContextFunc::new("foo", (arg(Some("bar"), 1), (arg(Some("baz"), 2), ())))
118            ),
119            Ok("fn foo(bar: 1, baz: 2)")
120        );
121    }
122
123    #[test]
124    fn test_func_colored_fmt() {
125        let mut buffer = [0; 128];
126
127        assert_eq!(
128            debug_fmt(
129                &mut buffer,
130                &AnsiColored::new(
131                    UnwindContextFunc::new("foo", (arg(Some("bar"), 1), (arg(Some("baz"), 2), ()))),
132                    &TEST_COLOR_SCHEME
133                )
134            ),
135            Ok(concat!(
136                "{FN}fn ",
137                "{FN_NAME}foo",
138                "{FN_BRACE}(",
139                "{DEF}bar: ",
140                "{NUM}1",
141                "{DEF}, baz: ",
142                "{NUM}2",
143                "{DEF}",
144                "{FN_BRACE}",
145                ")",
146                "{DEF}"
147            ))
148        );
149    }
150
151    #[test]
152    fn test_func_failed_fmt() {
153        let func = UnwindContextFunc::new("foo", (arg(Some("foo"), 1), (arg(Some("bar"), 2), ())));
154
155        let mut buffer = [0; 64];
156        let len = debug_fmt(&mut buffer, &func).unwrap().len();
157        for len in 0..len {
158            assert_eq!(debug_fmt(&mut buffer[0..len], &func), Err(FmtError));
159        }
160    }
161
162    #[test]
163    fn test_func_failed_colored_fmt() {
164        let func = AnsiColored::new(
165            UnwindContextFunc::new("foo", (arg(Some("foo"), 1), (arg(Some("bar"), 2), ()))),
166            &TEST_COLOR_SCHEME,
167        );
168
169        let mut buffer = [0; 128];
170        let len = debug_fmt(&mut buffer, &func).unwrap().len();
171        for len in 0..len {
172            assert_eq!(debug_fmt(&mut buffer[0..len], &func), Err(FmtError));
173        }
174    }
175}