amq_protocol_types/
parsing.rs

1use crate::{flags::*, types::*, value::*};
2use nom::{
3    self,
4    bytes::streaming::take,
5    combinator::{all_consuming, complete, flat_map, map, map_opt, map_parser, map_res},
6    error::{context, ContextError, ErrorKind, ParseError},
7    multi::fold_many0,
8    number::streaming::{
9        be_f32, be_f64, be_i16, be_i32, be_i64, be_u16, be_u32, be_u64, i8 as be_i8, u8 as be_u8,
10    },
11    sequence::pair,
12    Parser,
13};
14use std::{error, fmt};
15use traits::*;
16
17/// Error context for `ParserErrors`
18#[derive(Clone, Debug, Eq, PartialEq)]
19enum VerboseErrorKind {
20    /// Static string added by the `context` function
21    Context(&'static str),
22    /// Indicates which character was expected by the `char` function
23    Char(char),
24    /// Error kind given by various nom parsers
25    Nom(ErrorKind),
26}
27
28/// Struct holding the errors stack
29#[derive(Clone, Debug, PartialEq)]
30pub struct ParserErrors {
31    error: VerboseErrorKind,
32    errors: Option<Vec<VerboseErrorKind>>,
33}
34
35impl ParserErrors {
36    #[cfg(not(feature = "verbose-errors"))]
37    fn init_errors() -> Option<Vec<VerboseErrorKind>> {
38        None
39    }
40    #[cfg(feature = "verbose-errors")]
41    fn init_errors() -> Option<Vec<VerboseErrorKind>> {
42        Some(Vec::new())
43    }
44}
45
46impl<I> ParseError<I> for ParserErrors {
47    fn from_error_kind(_input: I, kind: ErrorKind) -> Self {
48        Self {
49            error: VerboseErrorKind::Nom(kind),
50            errors: Self::init_errors(),
51        }
52    }
53
54    fn append(_input: I, kind: ErrorKind, mut other: Self) -> Self {
55        if let Some(errors) = other.errors.as_mut() {
56            errors.push(VerboseErrorKind::Nom(kind));
57        }
58        other
59    }
60
61    fn from_char(_input: I, c: char) -> Self {
62        Self {
63            error: VerboseErrorKind::Char(c),
64            errors: Self::init_errors(),
65        }
66    }
67}
68
69impl<I> ContextError<I> for ParserErrors {
70    fn add_context(_input: I, ctx: &'static str, mut other: Self) -> Self {
71        if let Some(errors) = other.errors.as_mut() {
72            errors.push(VerboseErrorKind::Context(ctx));
73        }
74        other
75    }
76}
77
78impl<I, E> nom::error::FromExternalError<I, E> for ParserErrors {
79    fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
80        Self::from_error_kind(input, kind)
81    }
82}
83
84impl fmt::Display for ParserErrors {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        write!(f, "Parser error: {:?}", self.error)?;
87        if let Some(errors) = self.errors.as_ref() {
88            for error in errors {
89                writeln!(f)?;
90                write!(f, "\tat {:?}", error)?;
91            }
92        }
93        Ok(())
94    }
95}
96
97impl error::Error for ParserErrors {}
98
99/// Error returned by parsers
100pub type ParserError = nom::Err<ParserErrors>;
101/// Return type of parsers
102pub type ParserResult<I, T> = Result<(I, T), ParserError>;
103
104/// Parse the [AMQPValue](../type.AMQPValue.html) of the given [AMQPType](../type.AMQPType.html)
105pub fn parse_raw_value<I: ParsableInput>(
106    amqp_type: AMQPType,
107) -> impl Parser<I, Output = AMQPValue, Error = ParserErrors> {
108    context("parse_raw_value", move |i| match amqp_type {
109        AMQPType::Boolean => map(parse_boolean, AMQPValue::Boolean).parse(i),
110        AMQPType::ShortShortInt => map(parse_short_short_int, AMQPValue::ShortShortInt).parse(i),
111        AMQPType::ShortShortUInt => map(parse_short_short_uint, AMQPValue::ShortShortUInt).parse(i),
112        AMQPType::ShortInt => map(parse_short_int, AMQPValue::ShortInt).parse(i),
113        AMQPType::ShortUInt => map(parse_short_uint, AMQPValue::ShortUInt).parse(i),
114        AMQPType::LongInt => map(parse_long_int, AMQPValue::LongInt).parse(i),
115        AMQPType::LongUInt => map(parse_long_uint, AMQPValue::LongUInt).parse(i),
116        AMQPType::LongLongInt => map(parse_long_long_int, AMQPValue::LongLongInt).parse(i),
117        /* RabbitMQ treats LongLongUInt as a LongLongInt hence expose it as such */
118        AMQPType::LongLongUInt => map(parse_long_long_int, AMQPValue::LongLongInt).parse(i),
119        AMQPType::Float => map(parse_float, AMQPValue::Float).parse(i),
120        AMQPType::Double => map(parse_double, AMQPValue::Double).parse(i),
121        AMQPType::DecimalValue => map(parse_decimal_value, AMQPValue::DecimalValue).parse(i),
122        AMQPType::ShortString => map(parse_short_string, AMQPValue::ShortString).parse(i),
123        AMQPType::LongString => map(parse_long_string, AMQPValue::LongString).parse(i),
124        AMQPType::FieldArray => map(parse_field_array, AMQPValue::FieldArray).parse(i),
125        AMQPType::Timestamp => map(parse_timestamp, AMQPValue::Timestamp).parse(i),
126        AMQPType::FieldTable => map(parse_field_table, AMQPValue::FieldTable).parse(i),
127        AMQPType::ByteArray => map(parse_byte_array, AMQPValue::ByteArray).parse(i),
128        AMQPType::Void => Ok((i, AMQPValue::Void)),
129    })
130}
131
132/// Parse an [AMQPValue](../type.AMQPValue.html)
133pub fn parse_value<I: ParsableInput>(i: I) -> ParserResult<I, AMQPValue> {
134    context("parse_value", flat_map(parse_type, parse_raw_value)).parse(i)
135}
136
137/// Parse an [AMQPType](../type.AMQPType.html)
138pub fn parse_type<I: ParsableInput>(i: I) -> ParserResult<I, AMQPType> {
139    context(
140        "parse_type",
141        map_opt(be_u8, |t| AMQPType::from_id(t as char)),
142    )
143    .parse(i)
144}
145
146/// Parse an id [(ShortUInt)](../type.ShortUInt.html)
147pub fn parse_id<I: ParsableInput>(i: I) -> ParserResult<I, ShortUInt> {
148    context("parse_id", parse_short_uint).parse(i)
149}
150
151/// Parse a [Boolean](../type.Boolean.html)
152pub fn parse_boolean<I: ParsableInput>(i: I) -> ParserResult<I, Boolean> {
153    context("parse_boolean", map(be_u8, |b| b != 0)).parse(i)
154}
155
156/// Parse a [ShortShortInt](../type.ShortShortInt.html)
157pub fn parse_short_short_int<I: ParsableInput>(i: I) -> ParserResult<I, ShortShortInt> {
158    context("parse_short_short_int", be_i8).parse(i)
159}
160
161/// Parse a [ShortShortUInt](../type.ShortShortUInt.html)
162pub fn parse_short_short_uint<I: ParsableInput>(i: I) -> ParserResult<I, ShortShortUInt> {
163    context("parse_short_short_uint", be_u8).parse(i)
164}
165
166/// Parse a [ShortInt](../type.ShortInt.html)
167pub fn parse_short_int<I: ParsableInput>(i: I) -> ParserResult<I, ShortInt> {
168    context("parse_short_int", be_i16).parse(i)
169}
170
171/// Parse a [ShortUInt](../type.ShortUInt.html)
172pub fn parse_short_uint<I: ParsableInput>(i: I) -> ParserResult<I, ShortUInt> {
173    context("parse_short_uint", be_u16).parse(i)
174}
175
176/// Parse a [LongInt](../type.LongInt.html)
177pub fn parse_long_int<I: ParsableInput>(i: I) -> ParserResult<I, LongInt> {
178    context("parse_long_int", be_i32).parse(i)
179}
180
181/// Parse a [LongUInt](../type.LongUInt.html)
182pub fn parse_long_uint<I: ParsableInput>(i: I) -> ParserResult<I, LongUInt> {
183    context("parse_long_uint", be_u32).parse(i)
184}
185
186/// Parse a [LongLongInt](../type.LongLongInt.html)
187pub fn parse_long_long_int<I: ParsableInput>(i: I) -> ParserResult<I, LongLongInt> {
188    context("parse_long_long_int", be_i64).parse(i)
189}
190
191/// Parse a [LongLongUInt](../type.LongLongUInt.html)
192pub fn parse_long_long_uint<I: ParsableInput>(i: I) -> ParserResult<I, LongLongUInt> {
193    context("parse_long_long_uint", be_u64).parse(i)
194}
195
196/// Parse a [Float](../type.Float.html)
197pub fn parse_float<I: ParsableInput>(i: I) -> ParserResult<I, Float> {
198    context("parse_float", be_f32).parse(i)
199}
200
201/// Parse a [Double](../type.Double.html)
202pub fn parse_double<I: ParsableInput>(i: I) -> ParserResult<I, Double> {
203    context("parse_double", be_f64).parse(i)
204}
205
206/// Parse a [DecimalValue](../type.DecimalValue.html)
207pub fn parse_decimal_value<I: ParsableInput>(i: I) -> ParserResult<I, DecimalValue> {
208    context(
209        "parse_decimal_value",
210        map(
211            pair(parse_short_short_uint, parse_long_uint),
212            |(scale, value)| DecimalValue { scale, value },
213        ),
214    )
215    .parse(i)
216}
217
218fn make_str<I: Input<Item = u8>>(i: I) -> Result<String, std::string::FromUtf8Error> {
219    String::from_utf8(i.iter_elements().collect())
220}
221
222/// Parse a [ShortString](../type.ShortString.html)
223pub fn parse_short_string<I: ParsableInput>(i: I) -> ParserResult<I, ShortString> {
224    context(
225        "parse_short_string",
226        map(
227            map_res(flat_map(parse_short_short_uint, take), make_str),
228            ShortString::from,
229        ),
230    )
231    .parse(i)
232}
233
234/// Parse a [LongString](../type.LongString.html)
235pub fn parse_long_string<I: ParsableInput>(i: I) -> ParserResult<I, LongString> {
236    context(
237        "parse_long_string",
238        map(flat_map(parse_long_uint, take), |i: I| {
239            i.iter_elements().collect::<Vec<u8>>().into()
240        }),
241    )
242    .parse(i)
243}
244
245/// Parse a [FieldArray](../type.FieldArray.html)
246pub fn parse_field_array<I: ParsableInput>(i: I) -> ParserResult<I, FieldArray> {
247    context(
248        "parse_field_array",
249        map_parser(
250            flat_map(parse_long_uint, take),
251            all_consuming(fold_many0(
252                context("parse_field_array_entry", complete(parse_value)),
253                FieldArray::default,
254                |mut acc, elem| {
255                    acc.push(elem);
256                    acc
257                },
258            )),
259        ),
260    )
261    .parse(i)
262}
263
264/// Parse a [Timestamp](../type.Timestamp.html)
265pub fn parse_timestamp<I: ParsableInput>(i: I) -> ParserResult<I, Timestamp> {
266    context("parse_timestamp", parse_long_long_uint).parse(i)
267}
268
269/// Parse a [FieldTable](../type.FieldTable.html)
270pub fn parse_field_table<I: ParsableInput>(i: I) -> ParserResult<I, FieldTable> {
271    context(
272        "parse_field_table",
273        map_parser(
274            flat_map(parse_long_uint, take),
275            all_consuming(fold_many0(
276                context(
277                    "parse_field_table_entry",
278                    complete(pair(parse_short_string, parse_value)),
279                ),
280                FieldTable::default,
281                |mut acc, (key, value)| {
282                    acc.insert(key, value);
283                    acc
284                },
285            )),
286        ),
287    )
288    .parse(i)
289}
290
291/// Parse a [ByteArray](../type.ByteArray.html)
292pub fn parse_byte_array<I: ParsableInput>(i: I) -> ParserResult<I, ByteArray> {
293    context(
294        "parse_byte_array",
295        map(flat_map(parse_long_uint, take), |i: I| {
296            i.iter_elements().collect::<Vec<u8>>().into()
297        }),
298    )
299    .parse(i)
300}
301
302/// Parse the [AMQPFlags](../type.AMQPFlags.html) for which the names are provided
303pub fn parse_flags<I: ParsableInput>(i: I, names: &[&str]) -> ParserResult<I, AMQPFlags> {
304    context(
305        "parse_flags",
306        map(take((names.len() + 7) / 8), |b| {
307            AMQPFlags::from_bytes(names, b)
308        }),
309    )
310    .parse(i)
311}
312
313/// Traits required for parsing
314pub mod traits {
315    /// Reexport nom traits required for parsing
316    pub use nom::{Compare, CompareResult, Input, Needed};
317
318    /// Trait used to ensure we can properly parse input
319    pub trait ParsableInput: Clone + Compare<&'static [u8]> + Input<Item = u8> + PartialEq {}
320
321    impl<T: Clone + Compare<&'static [u8]> + Input<Item = u8> + PartialEq> ParsableInput for T {}
322}
323
324#[cfg(test)]
325mod test {
326    use super::*;
327
328    const EMPTY: &[u8] = b"";
329
330    #[test]
331    fn test_parse_value() {
332        assert_eq!(
333            parse_value(&[84, 42, 42, 42, 42, 42, 42, 42, 42][..]),
334            Ok((EMPTY, AMQPValue::Timestamp(3038287259199220266)))
335        );
336        assert_eq!(
337            parse_value(&[83, 0, 0, 0, 4, 116, 101, 115, 116][..]),
338            Ok((EMPTY, AMQPValue::LongString("test".into())))
339        );
340    }
341
342    #[test]
343    fn test_parse_raw_value() {
344        assert_eq!(
345            parse_raw_value(AMQPType::Timestamp).parse(&[42, 42, 42, 42, 42, 42, 42, 42][..]),
346            Ok((EMPTY, AMQPValue::Timestamp(3038287259199220266)))
347        );
348        assert_eq!(
349            parse_raw_value(AMQPType::LongString).parse(&[0, 0, 0, 4, 116, 101, 115, 116][..]),
350            Ok((EMPTY, AMQPValue::LongString("test".into())))
351        );
352        /* Test internal exceptions */
353        assert_eq!(
354            parse_raw_value(AMQPType::LongLongUInt).parse(&[42, 42, 42, 42, 42, 42, 42, 42][..]),
355            Ok((EMPTY, AMQPValue::LongLongInt(3038287259199220266)))
356        );
357        assert_eq!(
358            parse_raw_value(AMQPType::ShortString).parse(&[4, 116, 101, 115, 116][..]),
359            Ok((EMPTY, AMQPValue::ShortString("test".into())))
360        );
361    }
362
363    #[test]
364    fn test_parse_type() {
365        assert_eq!(parse_type(&[116][..]), Ok((EMPTY, AMQPType::Boolean)));
366        assert_eq!(parse_type(&[102][..]), Ok((EMPTY, AMQPType::Float)));
367    }
368
369    #[test]
370    fn test_parse_id() {
371        assert_eq!(parse_id(&[0, 0][..]), Ok((EMPTY, 0)));
372        assert_eq!(parse_id(&[255, 255][..]), Ok((EMPTY, 65535)));
373    }
374
375    #[test]
376    fn test_parse_boolean() {
377        assert_eq!(parse_boolean(&[0][..]), Ok((EMPTY, false)));
378        assert_eq!(parse_boolean(&[1][..]), Ok((EMPTY, true)));
379    }
380
381    #[test]
382    fn test_parse_short_short_int() {
383        assert_eq!(parse_short_short_int(&[0][..]), Ok((EMPTY, 0)));
384        assert_eq!(parse_short_short_int(&[255][..]), Ok((EMPTY, -1)));
385    }
386
387    #[test]
388    fn test_parse_short_short_uint() {
389        assert_eq!(parse_short_short_uint(&[0][..]), Ok((EMPTY, 0)));
390        assert_eq!(parse_short_short_uint(&[255][..]), Ok((EMPTY, 255)));
391    }
392
393    #[test]
394    fn test_parse_short_int() {
395        assert_eq!(parse_short_int(&[0, 0][..]), Ok((EMPTY, 0)));
396        assert_eq!(parse_short_int(&[255, 255][..]), Ok((EMPTY, -1)));
397    }
398
399    #[test]
400    fn test_parse_short_uint() {
401        assert_eq!(parse_short_uint(&[0, 0][..]), Ok((EMPTY, 0)));
402        assert_eq!(parse_short_uint(&[255, 255][..]), Ok((EMPTY, 65535)));
403    }
404
405    #[test]
406    fn test_parse_long_int() {
407        assert_eq!(parse_long_int(&[0, 0, 0, 0][..]), Ok((EMPTY, 0)));
408        assert_eq!(parse_long_int(&[255, 255, 255, 255][..]), Ok((EMPTY, -1)));
409    }
410
411    #[test]
412    fn test_parse_long_uint() {
413        assert_eq!(parse_long_uint(&[0, 0, 0, 0][..]), Ok((EMPTY, 0)));
414        assert_eq!(
415            parse_long_uint(&[255, 255, 255, 255][..]),
416            Ok((EMPTY, 4294967295))
417        );
418    }
419
420    #[test]
421    fn test_parse_long_long_int() {
422        assert_eq!(
423            parse_long_long_int(&[0, 0, 0, 0, 0, 0, 0, 0][..]),
424            Ok((EMPTY, 0))
425        );
426        assert_eq!(
427            parse_long_long_int(&[255, 255, 255, 255, 255, 255, 255, 255][..]),
428            Ok((EMPTY, -1))
429        );
430    }
431
432    #[test]
433    fn test_parse_long_long_uint() {
434        assert_eq!(
435            parse_long_long_uint(&[0, 0, 0, 0, 0, 0, 0, 0][..]),
436            Ok((EMPTY, 0))
437        );
438        assert_eq!(
439            parse_long_long_uint(&[255, 255, 255, 255, 255, 255, 255, 255][..]),
440            Ok((EMPTY, 18446744073709551615))
441        );
442    }
443
444    #[test]
445    fn test_parse_float() {
446        assert_eq!(parse_float(&[0, 0, 0, 0][..]), Ok((EMPTY, 0.)));
447        assert_eq!(parse_float(&[66, 41, 174, 20][..]), Ok((EMPTY, 42.42)));
448    }
449
450    #[test]
451    fn test_parse_double() {
452        assert_eq!(parse_double(&[0, 0, 0, 0, 0, 0, 0, 0][..]), Ok((EMPTY, 0.)));
453        assert_eq!(
454            parse_double(&[64, 69, 53, 194, 143, 92, 40, 246][..]),
455            Ok((EMPTY, 42.42))
456        );
457    }
458
459    #[test]
460    fn test_parse_decimal_value() {
461        assert_eq!(
462            parse_decimal_value(&[0, 0, 0, 0, 0][..]),
463            Ok((EMPTY, DecimalValue { scale: 0, value: 0 }))
464        );
465        assert_eq!(
466            parse_decimal_value(&[255, 255, 255, 255, 255][..]),
467            Ok((
468                EMPTY,
469                DecimalValue {
470                    scale: 255,
471                    value: 4294967295
472                }
473            ))
474        );
475    }
476
477    #[test]
478    fn test_parse_short_string() {
479        assert_eq!(
480            parse_short_string(&[0][..]),
481            Ok((EMPTY, ShortString::default()))
482        );
483        assert_eq!(
484            parse_short_string(&[4, 116, 101, 115, 116][..]),
485            Ok((EMPTY, "test".into()))
486        );
487    }
488
489    #[test]
490    fn test_parse_long_string() {
491        assert_eq!(
492            parse_long_string(&[0, 0, 0, 0][..]),
493            Ok((EMPTY, LongString::default()))
494        );
495        assert_eq!(
496            parse_long_string(&[0, 0, 0, 4, 116, 101, 115, 116][..]),
497            Ok((EMPTY, "test".into()))
498        );
499    }
500
501    #[test]
502    fn test_parse_field_array() {
503        assert_eq!(
504            parse_field_array(&[0, 0, 0, 0][..]),
505            Ok((EMPTY, FieldArray::default()))
506        );
507        assert_eq!(
508            parse_field_array(&[0, 0, 0, 10, 83, 0, 0, 0, 4, 116, 101, 115, 116, 86][..]),
509            Ok((
510                EMPTY,
511                vec![AMQPValue::LongString("test".into()), AMQPValue::Void].into()
512            ))
513        );
514    }
515
516    #[test]
517    fn test_parse_timestamp() {
518        assert_eq!(
519            parse_timestamp(&[0, 0, 0, 0, 0, 0, 0, 0][..]),
520            Ok((EMPTY, 0))
521        );
522        assert_eq!(
523            parse_timestamp(&[255, 255, 255, 255, 255, 255, 255, 255][..]),
524            Ok((EMPTY, 18446744073709551615))
525        );
526    }
527
528    #[test]
529    fn test_parse_field_table() {
530        let mut table = FieldTable::default();
531        table.insert("test".into(), AMQPValue::LongString("test".into()));
532        table.insert("tt".into(), AMQPValue::Void);
533        assert_eq!(
534            parse_field_table(&[0, 0, 0, 0][..]),
535            Ok((EMPTY, FieldTable::default()))
536        );
537        assert_eq!(
538            parse_field_table(
539                &[
540                    0, 0, 0, 18, 4, 116, 101, 115, 116, 83, 0, 0, 0, 4, 116, 101, 115, 116, 2, 116,
541                    116, 86
542                ][..]
543            ),
544            Ok((EMPTY, table))
545        );
546    }
547
548    #[test]
549    fn test_parse_byte_array() {
550        assert_eq!(
551            parse_byte_array(&[0, 0, 0, 0][..]),
552            Ok((EMPTY, ByteArray::default()))
553        );
554        assert_eq!(
555            parse_byte_array(&[0, 0, 0, 4, 42, 1, 2, 3][..]),
556            Ok((EMPTY, vec![42, 1, 2, 3].into()))
557        );
558    }
559
560    #[test]
561    fn test_parse_flags() {
562        let mut flags = AMQPFlags::default();
563        let mut names = Vec::new();
564        names.push("a");
565        flags.add_flag("a".to_string(), true);
566        names.push("b");
567        flags.add_flag("b".to_string(), false);
568        names.push("c");
569        flags.add_flag("c".to_string(), true);
570        names.push("d");
571        flags.add_flag("d".to_string(), true);
572        assert_eq!(
573            parse_flags(&[0b00001101][..], &names),
574            Ok((EMPTY, flags.clone()))
575        );
576        names.push("e");
577        flags.add_flag("e".to_string(), true);
578        names.push("f");
579        flags.add_flag("f".to_string(), false);
580        names.push("g");
581        flags.add_flag("g".to_string(), true);
582        names.push("h");
583        flags.add_flag("h".to_string(), true);
584        names.push("i");
585        flags.add_flag("i".to_string(), false);
586        names.push("j");
587        flags.add_flag("j".to_string(), true);
588        assert_eq!(
589            parse_flags(&[0b11011101, 0b00000010][..], &names),
590            Ok((EMPTY, flags))
591        );
592    }
593}