amq_protocol_types/
parsing.rs

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