unwind_context/
args.rs

1use core::fmt::{Debug, Formatter, Result as FmtResult};
2
3use crate::{AnsiColorScheme, AnsiColored, DebugAnsiColored, UnwindContextArg};
4
5/// A structure representing function argument names and their 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 UnwindContextArgs<Params>(
14    /// Function argument names and values in cons-like list representation.
15    pub Params,
16);
17
18impl<Params> UnwindContextArgs<Params> {
19    /// Create a new `UnwindContextArgs` with the provided parameters.
20    ///
21    /// Parameters are required to be represented as a recursive tuple list like
22    /// `(A, (B, (C, (D, ()))))` in order to be formatted.
23    ///
24    /// # Examples
25    ///
26    /// ```rust
27    /// use unwind_context::{UnwindContextArg, UnwindContextArgs};
28    ///
29    /// let args0 = UnwindContextArgs::new(());
30    ///
31    /// let args1 = UnwindContextArgs::new((UnwindContextArg::new(Some("first"), 123), ()));
32    ///
33    /// let args3 = UnwindContextArgs::new((
34    ///     UnwindContextArg::new(Some("first"), 123),
35    ///     (
36    ///         UnwindContextArg::new(Some("second"), "foo"),
37    ///         (UnwindContextArg::new(Some("third"), true), ()),
38    ///     ),
39    /// ));
40    /// ```
41    #[inline]
42    pub fn new(args: Params) -> Self {
43        Self(args)
44    }
45}
46
47impl Debug for UnwindContextArgs<()> {
48    #[inline]
49    fn fmt(&self, _: &mut Formatter<'_>) -> FmtResult {
50        Ok(())
51    }
52}
53
54impl Debug for UnwindContextArgs<&()> {
55    #[inline]
56    fn fmt(&self, _: &mut Formatter<'_>) -> FmtResult {
57        Ok(())
58    }
59}
60
61impl DebugAnsiColored for UnwindContextArgs<()> {
62    #[inline]
63    fn fmt_colored(&self, _: &mut Formatter<'_>, _: &'static AnsiColorScheme) -> FmtResult {
64        Ok(())
65    }
66}
67
68impl DebugAnsiColored for UnwindContextArgs<&()> {
69    #[inline]
70    fn fmt_colored(&self, _: &mut Formatter<'_>, _: &'static AnsiColorScheme) -> FmtResult {
71        Ok(())
72    }
73}
74
75impl<First, Rest> Debug for UnwindContextArgs<(First, Rest)>
76where
77    for<'a> UnwindContextArgs<&'a (First, Rest)>: Debug,
78{
79    #[inline]
80    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
81        Debug::fmt(&UnwindContextArgs(&self.0), f)?;
82        Ok(())
83    }
84}
85
86impl<First, Rest> DebugAnsiColored for UnwindContextArgs<(First, Rest)>
87where
88    for<'a> UnwindContextArgs<&'a (First, Rest)>: DebugAnsiColored,
89{
90    #[inline]
91    fn fmt_colored(
92        &self,
93        f: &mut Formatter<'_>,
94        color_scheme: &'static AnsiColorScheme,
95    ) -> FmtResult {
96        DebugAnsiColored::fmt_colored(&UnwindContextArgs(&self.0), f, color_scheme)?;
97        Ok(())
98    }
99}
100
101impl<First> Debug for UnwindContextArgs<&(UnwindContextArg<First>, ())>
102where
103    First: Debug,
104{
105    #[inline]
106    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
107        Debug::fmt(&self.0 .0, f)?;
108        Ok(())
109    }
110}
111
112impl<First> DebugAnsiColored for UnwindContextArgs<&(UnwindContextArg<First>, ())>
113where
114    First: Debug,
115{
116    #[inline]
117    fn fmt_colored(
118        &self,
119        f: &mut Formatter<'_>,
120        color_scheme: &'static AnsiColorScheme,
121    ) -> FmtResult {
122        DebugAnsiColored::fmt_colored(&self.0 .0, f, color_scheme)?;
123        Ok(())
124    }
125}
126
127impl<'a, First, Second, Rest> Debug
128    for UnwindContextArgs<&'a (UnwindContextArg<First>, (Second, Rest))>
129where
130    First: Debug,
131    UnwindContextArgs<&'a (Second, Rest)>: Debug,
132{
133    #[inline]
134    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
135        write!(f, "{:?}, {:?}", self.0 .0, UnwindContextArgs(&self.0 .1))?;
136        Ok(())
137    }
138}
139
140impl<'a, First, Second, Rest> DebugAnsiColored
141    for UnwindContextArgs<&'a (UnwindContextArg<First>, (Second, Rest))>
142where
143    First: Debug,
144    UnwindContextArgs<&'a (Second, Rest)>: DebugAnsiColored,
145{
146    #[inline]
147    fn fmt_colored(
148        &self,
149        f: &mut Formatter<'_>,
150        color_scheme: &'static AnsiColorScheme,
151    ) -> FmtResult {
152        write!(
153            f,
154            "{:?}, {:?}",
155            AnsiColored::new(&self.0 .0, color_scheme),
156            AnsiColored::new(UnwindContextArgs(&self.0 .1), color_scheme)
157        )?;
158        Ok(())
159    }
160}
161
162#[cfg(test)]
163mod tests {
164    use core::fmt::Error as FmtError;
165
166    use crate::test_common::{arg, args, colored_args};
167    use crate::test_util::debug_fmt;
168
169    #[test]
170    fn test_args_fmt() {
171        let mut buffer = [0; 64];
172
173        assert_eq!(debug_fmt(&mut buffer, &args(())), Ok(""));
174        assert_eq!(debug_fmt(&mut buffer, &args(&())), Ok(""));
175
176        assert_eq!(
177            debug_fmt(&mut buffer, &args((arg(Some("foo"), 1), ()))),
178            Ok("foo: 1")
179        );
180        assert_eq!(
181            debug_fmt(&mut buffer, &args(&(arg(Some("foo"), 1), ()))),
182            Ok("foo: 1")
183        );
184
185        assert_eq!(
186            debug_fmt(
187                &mut buffer,
188                &args(&(arg(Some("foo"), 1), (arg(Some("bar"), 2), ())))
189            ),
190            Ok("foo: 1, bar: 2")
191        );
192
193        assert_eq!(
194            debug_fmt(
195                &mut buffer,
196                &args(&(
197                    arg(Some("foo"), 1),
198                    (arg(Some("bar"), 2), (arg(Some("baz"), 3), ()))
199                ))
200            ),
201            Ok("foo: 1, bar: 2, baz: 3")
202        );
203
204        assert_eq!(
205            debug_fmt(
206                &mut buffer,
207                &args(&(
208                    arg(Some("foo"), 1),
209                    (arg(Some("bar"), 2), (arg(None, 3), ()))
210                ))
211            ),
212            Ok("foo: 1, bar: 2, 3")
213        );
214    }
215
216    #[test]
217    fn test_args_colored_fmt() {
218        let mut buffer = [0; 64];
219
220        assert_eq!(debug_fmt(&mut buffer, &colored_args(())), Ok(""));
221        assert_eq!(debug_fmt(&mut buffer, &colored_args(&())), Ok(""));
222
223        assert_eq!(
224            debug_fmt(&mut buffer, &colored_args((arg(Some("foo"), 1), ()))),
225            Ok("foo: {NUM}1{DEF}")
226        );
227
228        assert_eq!(
229            debug_fmt(
230                &mut buffer,
231                &colored_args(&(
232                    arg(Some("foo"), 1),
233                    (arg(Some("bar"), 2), (arg(None, 3), ()))
234                ))
235            ),
236            Ok("foo: {NUM}1{DEF}, bar: {NUM}2{DEF}, {NUM}3{DEF}")
237        );
238    }
239
240    #[test]
241    fn test_args_failed_fmt() {
242        let args = args((arg(Some("foo"), 1), (arg(Some("bar"), 2), ())));
243
244        let mut buffer = [0; 64];
245        let len = debug_fmt(&mut buffer, &args).unwrap().len();
246        for len in 0..len {
247            assert_eq!(debug_fmt(&mut buffer[0..len], &args), Err(FmtError));
248        }
249    }
250
251    #[test]
252    fn test_args_failed_colored_fmt() {
253        let args = colored_args((arg(Some("foo"), 1), (arg(Some("bar"), 2), ())));
254
255        let mut buffer = [0; 64];
256        let len = debug_fmt(&mut buffer, &args).unwrap().len();
257        for len in 0..len {
258            assert_eq!(debug_fmt(&mut buffer[0..len], &args), Err(FmtError));
259        }
260    }
261}