asn1_rs/
debug.rs

1#![allow(unused_imports)]
2
3use crate::ParseResult;
4
5pub(crate) mod macros {
6    macro_rules! debug_eprintln {
7    ($msg: expr, $( $args:expr ),* ) => {
8        #[cfg(feature = "debug")]
9        {
10            use colored::Colorize;
11            let s = $msg.to_string().green();
12            eprintln!("{} {}", s, format!($($args),*));
13        }
14    };
15}
16
17    #[allow(unused_macros)]
18    macro_rules! trace_eprintln {
19    ($msg: expr, $( $args:expr ),* ) => {
20        #[cfg(feature = "trace")]
21        {
22            use colored::Colorize;
23            let s = $msg.to_string().green();
24            eprintln!("{} {}", s, format!($($args),*));
25        }
26    };
27}
28
29    pub(crate) use debug_eprintln;
30    pub(crate) use trace_eprintln;
31}
32
33use macros::*;
34
35#[cfg(feature = "debug")]
36fn eprintln_hex_dump(bytes: &[u8], max_len: usize) {
37    use core::cmp::min;
38    use nom::HexDisplay;
39
40    let m = min(bytes.len(), max_len);
41    eprint!("{}", &bytes[..m].to_hex(16));
42    if bytes.len() > max_len {
43        eprintln!("... <continued>");
44    }
45}
46
47#[cfg(not(feature = "debug"))]
48#[inline]
49pub fn trace_generic<F, I, O, E>(_msg: &str, _fname: &str, f: F, input: I) -> Result<O, E>
50where
51    F: Fn(I) -> Result<O, E>,
52{
53    f(input)
54}
55
56#[cfg(feature = "debug")]
57pub fn trace_generic<F, I, O, E>(msg: &str, fname: &str, f: F, input: I) -> Result<O, E>
58where
59    F: Fn(I) -> Result<O, E>,
60    E: core::fmt::Display,
61{
62    trace_eprintln!(msg, "⤷ {}", fname);
63    let output = f(input);
64    match &output {
65        Err(e) => {
66            debug_eprintln!(msg, "↯ {} failed: {}", fname, e.to_string().red());
67        }
68        _ => {
69            debug_eprintln!(msg, "⤶ {}", fname);
70        }
71    }
72    output
73}
74
75#[cfg(not(feature = "debug"))]
76#[inline]
77pub fn trace<'a, T, E, F>(_msg: &str, f: F, input: &'a [u8]) -> ParseResult<'a, T, E>
78where
79    F: Fn(&'a [u8]) -> ParseResult<'a, T, E>,
80{
81    f(input)
82}
83
84#[cfg(feature = "debug")]
85pub fn trace<'a, T, E, F>(msg: &str, f: F, input: &'a [u8]) -> ParseResult<'a, T, E>
86where
87    F: Fn(&'a [u8]) -> ParseResult<'a, T, E>,
88{
89    trace_eprintln!(
90        msg,
91        "⤷ input (len={}, type={})",
92        input.len(),
93        core::any::type_name::<T>()
94    );
95    let res = f(input);
96    match &res {
97        Ok((_rem, _)) => {
98            trace_eprintln!(
99                msg,
100                "⤶ Parsed {} bytes, {} remaining",
101                input.len() - _rem.len(),
102                _rem.len()
103            );
104        }
105        Err(_) => {
106            // NOTE: we do not need to print error, caller should print it
107            debug_eprintln!(msg, "↯ Parsing failed at location:");
108            eprintln_hex_dump(input, 16);
109        }
110    }
111    res
112}
113
114#[cfg(feature = "debug")]
115#[cfg(test)]
116mod tests {
117
118    use std::collections::HashSet;
119
120    use crate::*;
121    use alloc::collections::BTreeSet;
122    use hex_literal::hex;
123
124    #[test]
125    fn debug_from_ber_any() {
126        assert!(Any::from_ber(&hex!("01 01 ff")).is_ok());
127    }
128
129    #[test]
130    fn debug_from_ber_failures() {
131        // wrong type
132        eprintln!("--");
133        assert!(<Vec<u16>>::from_ber(&hex!("02 01 00")).is_err());
134    }
135
136    #[test]
137    fn debug_from_ber_sequence_indefinite() {
138        let input = &hex!("30 80 02 03 01 00 01 00 00");
139        let (rem, result) = Sequence::from_ber(input).expect("parsing failed");
140        assert_eq!(result.as_ref(), &input[2..7]);
141        assert_eq!(rem, &[]);
142        eprintln!("--");
143        let (rem, result) = <Vec<u32>>::from_ber(input).expect("parsing failed");
144        assert_eq!(&result, &[65537]);
145        assert_eq!(rem, &[]);
146    }
147
148    #[test]
149    fn debug_from_ber_sequence_of() {
150        // parsing failure (wrong type)
151        let input = &hex!("30 03 01 01 00");
152        eprintln!("--");
153        let _ = <SequenceOf<u32>>::from_ber(input).expect_err("parsing should fail");
154        eprintln!("--");
155        let _ = <Vec<u32>>::from_ber(input).expect_err("parsing should fail");
156    }
157
158    #[test]
159    fn debug_from_ber_u32() {
160        assert!(u32::from_ber(&hex!("02 01 01")).is_ok());
161    }
162
163    #[test]
164    fn debug_from_der_any() {
165        assert!(Any::from_der(&hex!("01 01 ff")).is_ok());
166    }
167
168    #[test]
169    fn debug_from_der_bool() {
170        eprintln!("** first test is ok**");
171        assert!(<bool>::from_der(&hex!("01 01 ff")).is_ok());
172        eprintln!("** second test fails when parsing ANY (eof)**");
173        assert!(<bool>::from_der(&hex!("01 02 ff")).is_err());
174        eprintln!("** second test fails when checking DER constraints**");
175        assert!(<bool>::from_der(&hex!("01 01 f0")).is_err());
176        eprintln!("** second test fails during TryFrom**");
177        assert!(<bool>::from_der(&hex!("01 02 ff ff")).is_err());
178    }
179
180    #[test]
181    fn debug_from_der_failures() {
182        use crate::Sequence;
183
184        // parsing any failed
185        eprintln!("--");
186        assert!(u16::from_der(&hex!("ff 00")).is_err());
187        // Indefinite length
188        eprintln!("--");
189        assert!(u16::from_der(&hex!("30 80 00 00")).is_err());
190        // DER constraints failed
191        eprintln!("--");
192        assert!(bool::from_der(&hex!("01 01 7f")).is_err());
193        // Incomplete sequence
194        eprintln!("--");
195        let _ = Sequence::from_der(&hex!("30 81 04 00 00"));
196    }
197
198    #[test]
199    fn debug_from_der_sequence() {
200        // parsing OK, recursive
201        let input = &hex!("30 08 02 03 01 00 01 02 01 01");
202        let (rem, result) = <Vec<u32>>::from_der(input).expect("parsing failed");
203        assert_eq!(&result, &[65537, 1]);
204        assert_eq!(rem, &[]);
205    }
206
207    #[test]
208    fn debug_from_der_sequence_fail() {
209        // tag is wrong
210        let input = &hex!("31 03 01 01 44");
211        let _ = <Vec<bool>>::from_der(input).expect_err("parsing should fail");
212        // sequence is ok but contraint fails on element
213        let input = &hex!("30 03 01 01 44");
214        let _ = <Vec<bool>>::from_der(input).expect_err("parsing should fail");
215    }
216
217    #[test]
218    fn debug_from_der_sequence_of() {
219        use crate::SequenceOf;
220        // parsing failure (wrong type)
221        let input = &hex!("30 03 01 01 00");
222        eprintln!("--");
223        let _ = <SequenceOf<u32>>::from_der(input).expect_err("parsing should fail");
224        eprintln!("--");
225        let _ = <Vec<u32>>::from_der(input).expect_err("parsing should fail");
226    }
227
228    #[test]
229    fn debug_from_der_set_fail() {
230        // set is ok but contraint fails on element
231        let input = &hex!("31 03 01 01 44");
232        let _ = <BTreeSet<bool>>::from_der(input).expect_err("parsing should fail");
233    }
234
235    #[test]
236    fn debug_from_der_set_of() {
237        use crate::SetOf;
238        use alloc::collections::BTreeSet;
239
240        // parsing failure (wrong type)
241        let input = &hex!("31 03 01 01 00");
242        eprintln!("--");
243        let _ = <SetOf<u32>>::from_der(input).expect_err("parsing should fail");
244        eprintln!("--");
245        let _ = <BTreeSet<u32>>::from_der(input).expect_err("parsing should fail");
246        eprintln!("--");
247        let _ = <HashSet<u32>>::from_der(input).expect_err("parsing should fail");
248    }
249
250    #[test]
251    fn debug_from_der_string_ok() {
252        let input = &hex!("0c 0a 53 6f 6d 65 2d 53 74 61 74 65");
253        let (rem, result) = Utf8String::from_der(input).expect("parsing failed");
254        assert_eq!(result.as_ref(), "Some-State");
255        assert_eq!(rem, &[]);
256    }
257
258    #[test]
259    fn debug_from_der_string_fail() {
260        // wrong charset
261        let input = &hex!("12 03 41 42 43");
262        let _ = NumericString::from_der(input).expect_err("parsing should fail");
263    }
264}