Skip to main content

amq_protocol_types/
generation.rs

1/// Serialization types and traits
2pub use cookie_factory::{BackToTheBuffer, GenError, GenResult, SerializeFn};
3
4use crate::{flags::*, types::*, value::*};
5use cookie_factory::{
6    bytes::{be_f32, be_f64, be_i8, be_i16, be_i32, be_i64, be_u8, be_u16, be_u32, be_u64},
7    combinator::{back_to_the_buffer, slice},
8    multi::many_ref,
9    sequence::pair,
10};
11use std::io::Write;
12
13/// Apply a generator and serialize its length at the beginning of buffer
14pub fn gen_with_len<W: Write + BackToTheBuffer, F: SerializeFn<W>>(f: F) -> impl SerializeFn<W> {
15    back_to_the_buffer(
16        4,
17        move |x| {
18            let start = x.position;
19            let x = f(x)?;
20            let len = x.position - start;
21            Ok((x, len))
22        },
23        move |x, len| gen_long_uint(len as LongUInt)(x),
24    )
25}
26
27/// Generate the [AMQPValue](../type.AMQPValue.html) in the given buffer (x)
28pub fn gen_raw_value<'a, W: Write + BackToTheBuffer + 'a>(
29    v: &'a AMQPValue,
30) -> impl SerializeFn<W> + 'a {
31    move |x| match *v {
32        AMQPValue::Boolean(b) => gen_boolean(b)(x),
33        AMQPValue::ShortShortInt(i) => gen_short_short_int(i)(x),
34        AMQPValue::ShortShortUInt(u) => gen_short_short_uint(u)(x),
35        AMQPValue::ShortInt(i) => gen_short_int(i)(x),
36        AMQPValue::ShortUInt(u) => gen_short_uint(u)(x),
37        AMQPValue::LongInt(i) => gen_long_int(i)(x),
38        AMQPValue::LongUInt(u) => gen_long_uint(u)(x),
39        AMQPValue::LongLongInt(i) => gen_long_long_int(i)(x),
40        AMQPValue::Float(f) => gen_float(f)(x),
41        AMQPValue::Double(d) => gen_double(d)(x),
42        AMQPValue::DecimalValue(d) => gen_decimal_value(d)(x),
43        AMQPValue::ShortString(ref s) => gen_short_string(s.as_str())(x),
44        AMQPValue::LongString(ref s) => gen_long_string(s.as_bytes())(x),
45        AMQPValue::FieldArray(ref a) => gen_field_array(a)(x),
46        AMQPValue::Timestamp(t) => gen_timestamp(t)(x),
47        AMQPValue::FieldTable(ref t) => gen_field_table(t)(x),
48        AMQPValue::ByteArray(ref a) => gen_byte_array(a)(x),
49        AMQPValue::Void => Ok(x),
50    }
51}
52
53/// Generate the [AMQPValue](../type.AMQPValue.html) preceded with its [AMQPType](../type.AMQPType.html) in the given buffer (x)
54pub fn gen_value<'a, W: Write + BackToTheBuffer + 'a>(
55    v: &'a AMQPValue,
56) -> impl SerializeFn<W> + 'a {
57    pair(gen_type(v.get_type()), gen_raw_value(v))
58}
59
60/// Generate the [AMQPType](../type.AMQPType.html) in the given buffer (x)
61pub fn gen_type<W: Write>(t: AMQPType) -> impl SerializeFn<W> {
62    gen_short_short_uint(t.get_id() as ShortShortUInt)
63}
64
65/// Generate the id ([ShortUInt](../type.ShortUInt.html)) in the given buffer (x)
66pub fn gen_id<W: Write>(id: ShortUInt) -> impl SerializeFn<W> {
67    gen_short_uint(id)
68}
69
70/// Generate the [Boolean](../type.Boolean.html) in the given buffer (x)
71pub fn gen_boolean<W: Write>(b: Boolean) -> impl SerializeFn<W> {
72    gen_short_short_uint(if b { 1 } else { 0 })
73}
74
75/// Generate the [ShortShortInt](../type.ShortShortInt.html) in the given buffer (x)
76pub fn gen_short_short_int<W: Write>(i: ShortShortInt) -> impl SerializeFn<W> {
77    be_i8(i)
78}
79
80/// Generate the [ShortShortUInt](../type.ShortShortUInt.html) in the given buffer (x)
81pub fn gen_short_short_uint<W: Write>(u: ShortShortUInt) -> impl SerializeFn<W> {
82    be_u8(u)
83}
84
85/// Generate the [ShortInt](../type.ShortInt.html) in the given buffer (x)
86pub fn gen_short_int<W: Write>(i: ShortInt) -> impl SerializeFn<W> {
87    be_i16(i)
88}
89
90/// Generate the [ShortUInt](../type.ShortUInt.html) in the given buffer (x)
91pub fn gen_short_uint<W: Write>(u: ShortUInt) -> impl SerializeFn<W> {
92    be_u16(u)
93}
94
95/// Generate the [LongInt](../type.LongInt.html) in the given buffer (x)
96pub fn gen_long_int<W: Write>(i: LongInt) -> impl SerializeFn<W> {
97    be_i32(i)
98}
99
100/// Generate the [LongUInt](../type.LongUInt.html) in the given buffer (x)
101pub fn gen_long_uint<W: Write>(u: LongUInt) -> impl SerializeFn<W> {
102    be_u32(u)
103}
104
105/// Generate the [LongLongInt](../type.LongLongInt.html) in the given buffer (x)
106pub fn gen_long_long_int<W: Write>(i: LongLongInt) -> impl SerializeFn<W> {
107    be_i64(i)
108}
109
110/// Generate the [LongLongUInt](../type.LongLongUInt.html) in the given buffer (x)
111pub fn gen_long_long_uint<W: Write>(u: LongLongUInt) -> impl SerializeFn<W> {
112    be_u64(u)
113}
114
115/// Generate the [Float](../type.Float.html) in the given buffer (x)
116pub fn gen_float<W: Write>(f: Float) -> impl SerializeFn<W> {
117    be_f32(f)
118}
119
120/// Generate the [Double](../type.Double.html) in the given buffer (x)
121pub fn gen_double<W: Write>(d: Double) -> impl SerializeFn<W> {
122    be_f64(d)
123}
124
125/// Generate the [DecimalValue](../type.DecimalValue.html) in the given buffer (x)
126pub fn gen_decimal_value<W: Write>(d: DecimalValue) -> impl SerializeFn<W> {
127    pair(gen_short_short_uint(d.scale), gen_long_uint(d.value))
128}
129
130/// Generate the [ShortString](../type.ShortString.html) in the given buffer (x)
131pub fn gen_short_string<'a, W: Write + 'a>(s: &'a str) -> impl SerializeFn<W> + 'a {
132    debug_assert!(
133        s.len() <= ShortShortUInt::MAX as usize,
134        "short string exceeds 255 bytes"
135    );
136    pair(
137        gen_short_short_uint(s.len() as ShortShortUInt),
138        slice(s.as_bytes()),
139    )
140}
141
142/// Generate the [LongString](../type.LongString.html) in the given buffer (x)
143pub fn gen_long_string<'a, W: Write + 'a>(s: &'a [u8]) -> impl SerializeFn<W> + 'a {
144    debug_assert!(
145        s.len() <= LongUInt::MAX as usize,
146        "long string exceeds 4 GiB"
147    );
148    pair(gen_long_uint(s.len() as LongUInt), slice(s))
149}
150
151/// Generate the [FieldArray](../type.FieldArray.html) in the given buffer (x)
152pub fn gen_field_array<'a, W: Write + BackToTheBuffer + 'a>(
153    a: &'a FieldArray,
154) -> impl SerializeFn<W> + 'a {
155    gen_with_len(many_ref(a.as_slice(), move |field| gen_value(field)))
156}
157
158/// Generate the [Timestamp](../type.Timestamp.html) in the given buffer (x)
159pub fn gen_timestamp<W: Write>(t: Timestamp) -> impl SerializeFn<W> {
160    gen_long_long_uint(t)
161}
162
163/// Generate the [FieldTable](../type.FieldTable.html) in the given buffer (x)
164pub fn gen_field_table<'a, W: Write + BackToTheBuffer + 'a>(
165    t: &'a FieldTable,
166) -> impl SerializeFn<W> + 'a {
167    gen_with_len(many_ref(t, gen_field_entry))
168}
169
170fn gen_field_entry<'a, W: Write + BackToTheBuffer + 'a>(
171    e: (&'a ShortString, &'a AMQPValue),
172) -> impl SerializeFn<W> + 'a {
173    pair(gen_short_string(e.0.as_str()), gen_value(e.1))
174}
175
176/// Generate the [ByteArray](../type.ByteArray.html) in the given buffer (x)
177pub fn gen_byte_array<'a, W: Write + 'a>(a: &'a ByteArray) -> impl SerializeFn<W> + 'a {
178    debug_assert!(
179        a.len() <= LongUInt::MAX as usize,
180        "byte array exceeds 4 GiB"
181    );
182    pair(gen_long_uint(a.len() as LongUInt), slice(a.as_slice()))
183}
184
185/// Generate the [AMQPFlags](../type.AMQPFlags.html) in the given buffer (x)
186pub fn gen_flags<'a, W: Write + 'a>(f: &'a AMQPFlags) -> impl SerializeFn<W> + 'a {
187    move |x| {
188        f.get_bytes()
189            .iter()
190            .try_fold(x, |acc, b| gen_short_short_uint(*b)(acc))
191    }
192}
193
194#[cfg(test)]
195mod test {
196    use super::*;
197
198    use cookie_factory::r#gen as cf_gen;
199
200    macro_rules! test_gen (
201        ($buf: expr, $gen: ident, $val: expr) => ({
202            let buf = $buf;
203            let len = cf_gen($gen($val), &mut buf[..]).map(|t| t.1);
204            match len {
205                Err(e)  => Err(format!("{:?}", e)),
206                Ok(len) => Ok((buf.to_vec(), len)),
207            }
208        });
209    );
210
211    #[test]
212    fn test_gen_raw_value() {
213        assert_eq!(
214            test_gen!(
215                &mut [0, 0, 0, 0][..],
216                gen_raw_value,
217                &AMQPValue::LongInt(42)
218            ),
219            Ok((vec![0, 0, 0, 42], 4))
220        );
221        assert_eq!(
222            test_gen!(&mut [0][..], gen_raw_value, &AMQPValue::Boolean(true)),
223            Ok((vec![1], 1))
224        );
225    }
226
227    #[test]
228    fn test_gen_value() {
229        assert_eq!(
230            test_gen!(&mut [0, 0, 0, 0, 0][..], gen_value, &AMQPValue::LongInt(42)),
231            Ok((vec![73, 0, 0, 0, 42], 5))
232        );
233        assert_eq!(
234            test_gen!(&mut [0, 0][..], gen_value, &AMQPValue::Boolean(true)),
235            Ok((vec![116, 1], 2))
236        );
237    }
238
239    #[test]
240    fn test_gen_type() {
241        assert_eq!(
242            test_gen!(&mut [0][..], gen_type, AMQPType::ShortShortInt),
243            Ok((vec![98], 1))
244        );
245        assert_eq!(
246            test_gen!(&mut [0][..], gen_type, AMQPType::ShortInt),
247            Ok((vec![115], 1))
248        );
249    }
250
251    #[test]
252    fn test_gen_id() {
253        assert_eq!(test_gen!(&mut [0, 0][..], gen_id, 0), Ok((vec![0, 0], 2)));
254        assert_eq!(
255            test_gen!(&mut [0, 0][..], gen_id, 65535),
256            Ok((vec![255, 255], 2))
257        );
258    }
259
260    #[test]
261    fn test_gen_boolean() {
262        assert_eq!(
263            test_gen!(&mut [0][..], gen_boolean, false),
264            Ok((vec![0], 1))
265        );
266        assert_eq!(test_gen!(&mut [0][..], gen_boolean, true), Ok((vec![1], 1)));
267    }
268
269    #[test]
270    fn test_gen_short_short_int() {
271        assert_eq!(
272            test_gen!(&mut [0][..], gen_short_short_int, 0),
273            Ok((vec![0], 1))
274        );
275        assert_eq!(
276            test_gen!(&mut [0][..], gen_short_short_int, -1),
277            Ok((vec![255], 1))
278        );
279    }
280
281    #[test]
282    fn test_gen_short_short_uint() {
283        assert_eq!(
284            test_gen!(&mut [0][..], gen_short_short_uint, 0),
285            Ok((vec![0], 1))
286        );
287        assert_eq!(
288            test_gen!(&mut [0][..], gen_short_short_uint, 255),
289            Ok((vec![255], 1))
290        );
291    }
292
293    #[test]
294    fn test_gen_short_int() {
295        assert_eq!(
296            test_gen!(&mut [0, 0][..], gen_short_int, 0),
297            Ok((vec![0, 0], 2))
298        );
299        assert_eq!(
300            test_gen!(&mut [0, 0][..], gen_short_int, -1),
301            Ok((vec![255, 255], 2))
302        );
303    }
304
305    #[test]
306    fn test_gen_short_uint() {
307        assert_eq!(
308            test_gen!(&mut [0, 0][..], gen_short_uint, 0),
309            Ok((vec![0, 0], 2))
310        );
311        assert_eq!(
312            test_gen!(&mut [0, 0][..], gen_short_uint, 65535),
313            Ok((vec![255, 255], 2))
314        );
315    }
316
317    #[test]
318    fn test_gen_long_int() {
319        assert_eq!(
320            test_gen!(&mut [0, 0, 0, 0][..], gen_long_int, 0),
321            Ok((vec![0, 0, 0, 0], 4))
322        );
323        assert_eq!(
324            test_gen!(&mut [0, 0, 0, 0][..], gen_long_int, -1),
325            Ok((vec![255, 255, 255, 255], 4))
326        );
327    }
328
329    #[test]
330    fn test_gen_long_uint() {
331        assert_eq!(
332            test_gen!(&mut [0, 0, 0, 0][..], gen_long_uint, 0),
333            Ok((vec![0, 0, 0, 0], 4))
334        );
335        assert_eq!(
336            test_gen!(&mut [0, 0, 0, 0][..], gen_long_uint, 4294967295),
337            Ok((vec![255, 255, 255, 255], 4))
338        );
339    }
340
341    #[test]
342    fn test_gen_long_long_int() {
343        assert_eq!(
344            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_long_int, 0),
345            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
346        );
347        assert_eq!(
348            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_long_int, -1),
349            Ok((vec![255, 255, 255, 255, 255, 255, 255, 255], 8))
350        );
351    }
352
353    #[test]
354    fn test_gen_long_long_uint() {
355        assert_eq!(
356            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_long_uint, 0),
357            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
358        );
359        assert_eq!(
360            test_gen!(
361                &mut [0, 0, 0, 0, 0, 0, 0, 0][..],
362                gen_long_long_uint,
363                18446744073709551615
364            ),
365            Ok((vec![255, 255, 255, 255, 255, 255, 255, 255], 8))
366        );
367    }
368
369    #[test]
370    fn test_gen_float() {
371        assert_eq!(
372            test_gen!(&mut [0, 0, 0, 0][..], gen_float, 0.),
373            Ok((vec![0, 0, 0, 0], 4))
374        );
375        assert_eq!(
376            test_gen!(&mut [0, 0, 0, 0][..], gen_float, 42.42),
377            Ok((vec![66, 41, 174, 20], 4))
378        );
379    }
380
381    #[test]
382    fn test_gen_double() {
383        assert_eq!(
384            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_double, 0.),
385            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
386        );
387        assert_eq!(
388            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_double, 42.42),
389            Ok((vec![64, 69, 53, 194, 143, 92, 40, 246], 8))
390        );
391    }
392
393    #[test]
394    fn test_gen_decimal_value() {
395        assert_eq!(
396            test_gen!(
397                &mut [0, 0, 0, 0, 0][..],
398                gen_decimal_value,
399                DecimalValue { scale: 0, value: 0 }
400            ),
401            Ok((vec![0, 0, 0, 0, 0], 5))
402        );
403        assert_eq!(
404            test_gen!(
405                &mut [0, 0, 0, 0, 0][..],
406                gen_decimal_value,
407                DecimalValue {
408                    scale: 2,
409                    value: 42
410                }
411            ),
412            Ok((vec![2, 0, 0, 0, 42], 5))
413        );
414    }
415
416    #[test]
417    fn test_gen_short_string() {
418        assert_eq!(
419            test_gen!(&mut [0][..], gen_short_string, ""),
420            Ok((vec![0], 1))
421        );
422        assert_eq!(
423            test_gen!(&mut [0, 0, 0, 0, 0][..], gen_short_string, "test"),
424            Ok((vec![4, 116, 101, 115, 116], 5))
425        );
426    }
427
428    #[test]
429    fn test_gen_long_string() {
430        assert_eq!(
431            test_gen!(&mut [0, 0, 0, 0][..], gen_long_string, &[]),
432            Ok((vec![0, 0, 0, 0], 4))
433        );
434        assert_eq!(
435            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_string, b"test"),
436            Ok((vec![0, 0, 0, 4, 116, 101, 115, 116], 8))
437        );
438    }
439
440    #[test]
441    fn test_gen_field_array() {
442        assert_eq!(
443            test_gen!(
444                &mut [0, 0, 0, 0][..],
445                gen_field_array,
446                &FieldArray::default()
447            ),
448            Ok((vec![0, 0, 0, 0], 4))
449        );
450        assert_eq!(
451            test_gen!(
452                &mut [0, 0, 0, 0, 0, 0][..],
453                gen_field_array,
454                &vec![AMQPValue::Boolean(true)].into()
455            ),
456            Ok((vec![0, 0, 0, 2, 116, 1], 6))
457        );
458    }
459
460    #[test]
461    fn test_gen_timestamp() {
462        assert_eq!(
463            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_timestamp, 0),
464            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
465        );
466        assert_eq!(
467            test_gen!(
468                &mut [0, 0, 0, 0, 0, 0, 0, 0][..],
469                gen_timestamp,
470                18446744073709551615
471            ),
472            Ok((vec![255, 255, 255, 255, 255, 255, 255, 255], 8))
473        );
474    }
475
476    #[test]
477    fn test_gen_field_table() {
478        let mut table = FieldTable::default();
479        table.insert("test".into(), AMQPValue::Float(42.42));
480        table.insert("test2".into(), AMQPValue::Boolean(false));
481        assert_eq!(
482            test_gen!(
483                &mut [0, 0, 0, 0][..],
484                gen_field_table,
485                &FieldTable::default()
486            ),
487            Ok((vec![0, 0, 0, 0], 4))
488        );
489        assert_eq!(
490            test_gen!(
491                &mut [
492                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
493                ][..],
494                gen_field_table,
495                &table
496            ),
497            Ok((
498                vec![
499                    0, 0, 0, 18, 4, 116, 101, 115, 116, 102, 66, 41, 174, 20, 5, 116, 101, 115,
500                    116, 50, 116, 0
501                ],
502                22
503            ))
504        );
505    }
506
507    #[test]
508    fn test_gen_byte_array() {
509        assert_eq!(
510            test_gen!(&mut [0, 0, 0, 0][..], gen_byte_array, &ByteArray::default()),
511            Ok((vec![0, 0, 0, 0], 4))
512        );
513        assert_eq!(
514            test_gen!(
515                &mut [0, 0, 0, 0, 0, 0, 0, 0][..],
516                gen_byte_array,
517                &vec![42, 1, 2, 3].into()
518            ),
519            Ok((vec![0, 0, 0, 4, 42, 1, 2, 3], 8))
520        );
521    }
522
523    #[test]
524    fn test_gen_flags() {
525        let mut flags = AMQPFlags::default();
526        flags.add_flag("a".to_string(), true);
527        flags.add_flag("b".to_string(), false);
528        flags.add_flag("c".to_string(), true);
529        flags.add_flag("d".to_string(), true);
530        assert_eq!(
531            test_gen!(&mut [0][..], gen_flags, &flags),
532            Ok((vec![0b00001101], 1))
533        );
534        flags.add_flag("e".to_string(), true);
535        flags.add_flag("f".to_string(), false);
536        flags.add_flag("g".to_string(), true);
537        flags.add_flag("h".to_string(), true);
538        flags.add_flag("i".to_string(), false);
539        flags.add_flag("j".to_string(), true);
540        assert_eq!(
541            test_gen!(&mut [0, 0][..], gen_flags, &flags),
542            Ok((vec![0b11011101, 0b00000010], 2))
543        );
544    }
545}