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    pair(
133        gen_short_short_uint(s.len() as ShortShortUInt),
134        slice(s.as_bytes()),
135    )
136}
137
138/// Generate the [LongString](../type.LongString.html) in the given buffer (x)
139pub fn gen_long_string<'a, W: Write + 'a>(s: &'a [u8]) -> impl SerializeFn<W> + 'a {
140    pair(gen_long_uint(s.len() as LongUInt), slice(s))
141}
142
143/// Generate the [FieldArray](../type.FieldArray.html) in the given buffer (x)
144pub fn gen_field_array<'a, W: Write + BackToTheBuffer + 'a>(
145    a: &'a FieldArray,
146) -> impl SerializeFn<W> + 'a {
147    gen_with_len(many_ref(a.as_slice(), move |field| gen_value(field)))
148}
149
150/// Generate the [Timestamp](../type.Timestamp.html) in the given buffer (x)
151pub fn gen_timestamp<W: Write>(t: Timestamp) -> impl SerializeFn<W> {
152    gen_long_long_uint(t)
153}
154
155/// Generate the [FieldTable](../type.FieldTable.html) in the given buffer (x)
156pub fn gen_field_table<'a, W: Write + BackToTheBuffer + 'a>(
157    t: &'a FieldTable,
158) -> impl SerializeFn<W> + 'a {
159    gen_with_len(many_ref(t, gen_field_entry))
160}
161
162fn gen_field_entry<'a, W: Write + BackToTheBuffer + 'a>(
163    e: (&'a ShortString, &'a AMQPValue),
164) -> impl SerializeFn<W> + 'a {
165    pair(gen_short_string(e.0.as_str()), gen_value(e.1))
166}
167
168/// Generate the [ByteArray](../type.ByteArray.html) in the given buffer (x)
169pub fn gen_byte_array<'a, W: Write + 'a>(a: &'a ByteArray) -> impl SerializeFn<W> + 'a {
170    pair(gen_long_uint(a.len() as LongUInt), slice(a.as_slice()))
171}
172
173/// Generate the [AMQPFlags](../type.AMQPFlags.html) in the given buffer (x)
174pub fn gen_flags<'a, W: Write + 'a>(f: &'a AMQPFlags) -> impl SerializeFn<W> + 'a {
175    move |x| {
176        f.get_bytes()
177            .iter()
178            .try_fold(x, |acc, b| gen_short_short_uint(*b)(acc))
179    }
180}
181
182#[cfg(test)]
183mod test {
184    use super::*;
185
186    use cookie_factory::r#gen as cf_gen;
187
188    macro_rules! test_gen (
189        ($buf: expr, $gen: ident, $val: expr) => ({
190            let buf = $buf;
191            let len = cf_gen($gen($val), &mut buf[..]).map(|t| t.1);
192            match len {
193                Err(e)  => Err(format!("{:?}", e)),
194                Ok(len) => Ok((buf.to_vec(), len)),
195            }
196        });
197    );
198
199    #[test]
200    fn test_gen_raw_value() {
201        assert_eq!(
202            test_gen!(
203                &mut [0, 0, 0, 0][..],
204                gen_raw_value,
205                &AMQPValue::LongInt(42)
206            ),
207            Ok((vec![0, 0, 0, 42], 4))
208        );
209        assert_eq!(
210            test_gen!(&mut [0][..], gen_raw_value, &AMQPValue::Boolean(true)),
211            Ok((vec![1], 1))
212        );
213    }
214
215    #[test]
216    fn test_gen_value() {
217        assert_eq!(
218            test_gen!(&mut [0, 0, 0, 0, 0][..], gen_value, &AMQPValue::LongInt(42)),
219            Ok((vec![73, 0, 0, 0, 42], 5))
220        );
221        assert_eq!(
222            test_gen!(&mut [0, 0][..], gen_value, &AMQPValue::Boolean(true)),
223            Ok((vec![116, 1], 2))
224        );
225    }
226
227    #[test]
228    fn test_gen_type() {
229        assert_eq!(
230            test_gen!(&mut [0][..], gen_type, AMQPType::ShortShortInt),
231            Ok((vec![98], 1))
232        );
233        assert_eq!(
234            test_gen!(&mut [0][..], gen_type, AMQPType::ShortInt),
235            Ok((vec![115], 1))
236        );
237    }
238
239    #[test]
240    fn test_gen_id() {
241        assert_eq!(test_gen!(&mut [0, 0][..], gen_id, 0), Ok((vec![0, 0], 2)));
242        assert_eq!(
243            test_gen!(&mut [0, 0][..], gen_id, 65535),
244            Ok((vec![255, 255], 2))
245        );
246    }
247
248    #[test]
249    fn test_gen_boolean() {
250        assert_eq!(
251            test_gen!(&mut [0][..], gen_boolean, false),
252            Ok((vec![0], 1))
253        );
254        assert_eq!(test_gen!(&mut [0][..], gen_boolean, true), Ok((vec![1], 1)));
255    }
256
257    #[test]
258    fn test_gen_short_short_int() {
259        assert_eq!(
260            test_gen!(&mut [0][..], gen_short_short_int, 0),
261            Ok((vec![0], 1))
262        );
263        assert_eq!(
264            test_gen!(&mut [0][..], gen_short_short_int, -1),
265            Ok((vec![255], 1))
266        );
267    }
268
269    #[test]
270    fn test_gen_short_short_uint() {
271        assert_eq!(
272            test_gen!(&mut [0][..], gen_short_short_uint, 0),
273            Ok((vec![0], 1))
274        );
275        assert_eq!(
276            test_gen!(&mut [0][..], gen_short_short_uint, 255),
277            Ok((vec![255], 1))
278        );
279    }
280
281    #[test]
282    fn test_gen_short_int() {
283        assert_eq!(
284            test_gen!(&mut [0, 0][..], gen_short_int, 0),
285            Ok((vec![0, 0], 2))
286        );
287        assert_eq!(
288            test_gen!(&mut [0, 0][..], gen_short_int, -1),
289            Ok((vec![255, 255], 2))
290        );
291    }
292
293    #[test]
294    fn test_gen_short_uint() {
295        assert_eq!(
296            test_gen!(&mut [0, 0][..], gen_short_uint, 0),
297            Ok((vec![0, 0], 2))
298        );
299        assert_eq!(
300            test_gen!(&mut [0, 0][..], gen_short_uint, 65535),
301            Ok((vec![255, 255], 2))
302        );
303    }
304
305    #[test]
306    fn test_gen_long_int() {
307        assert_eq!(
308            test_gen!(&mut [0, 0, 0, 0][..], gen_long_int, 0),
309            Ok((vec![0, 0, 0, 0], 4))
310        );
311        assert_eq!(
312            test_gen!(&mut [0, 0, 0, 0][..], gen_long_int, -1),
313            Ok((vec![255, 255, 255, 255], 4))
314        );
315    }
316
317    #[test]
318    fn test_gen_long_uint() {
319        assert_eq!(
320            test_gen!(&mut [0, 0, 0, 0][..], gen_long_uint, 0),
321            Ok((vec![0, 0, 0, 0], 4))
322        );
323        assert_eq!(
324            test_gen!(&mut [0, 0, 0, 0][..], gen_long_uint, 4294967295),
325            Ok((vec![255, 255, 255, 255], 4))
326        );
327    }
328
329    #[test]
330    fn test_gen_long_long_int() {
331        assert_eq!(
332            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_long_int, 0),
333            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
334        );
335        assert_eq!(
336            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_long_int, -1),
337            Ok((vec![255, 255, 255, 255, 255, 255, 255, 255], 8))
338        );
339    }
340
341    #[test]
342    fn test_gen_long_long_uint() {
343        assert_eq!(
344            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_long_uint, 0),
345            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
346        );
347        assert_eq!(
348            test_gen!(
349                &mut [0, 0, 0, 0, 0, 0, 0, 0][..],
350                gen_long_long_uint,
351                18446744073709551615
352            ),
353            Ok((vec![255, 255, 255, 255, 255, 255, 255, 255], 8))
354        );
355    }
356
357    #[test]
358    fn test_gen_float() {
359        assert_eq!(
360            test_gen!(&mut [0, 0, 0, 0][..], gen_float, 0.),
361            Ok((vec![0, 0, 0, 0], 4))
362        );
363        assert_eq!(
364            test_gen!(&mut [0, 0, 0, 0][..], gen_float, 42.42),
365            Ok((vec![66, 41, 174, 20], 4))
366        );
367    }
368
369    #[test]
370    fn test_gen_double() {
371        assert_eq!(
372            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_double, 0.),
373            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
374        );
375        assert_eq!(
376            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_double, 42.42),
377            Ok((vec![64, 69, 53, 194, 143, 92, 40, 246], 8))
378        );
379    }
380
381    #[test]
382    fn test_gen_decimal_value() {
383        assert_eq!(
384            test_gen!(
385                &mut [0, 0, 0, 0, 0][..],
386                gen_decimal_value,
387                DecimalValue { scale: 0, value: 0 }
388            ),
389            Ok((vec![0, 0, 0, 0, 0], 5))
390        );
391        assert_eq!(
392            test_gen!(
393                &mut [0, 0, 0, 0, 0][..],
394                gen_decimal_value,
395                DecimalValue {
396                    scale: 2,
397                    value: 42
398                }
399            ),
400            Ok((vec![2, 0, 0, 0, 42], 5))
401        );
402    }
403
404    #[test]
405    fn test_gen_short_string() {
406        assert_eq!(
407            test_gen!(&mut [0][..], gen_short_string, ""),
408            Ok((vec![0], 1))
409        );
410        assert_eq!(
411            test_gen!(&mut [0, 0, 0, 0, 0][..], gen_short_string, "test"),
412            Ok((vec![4, 116, 101, 115, 116], 5))
413        );
414    }
415
416    #[test]
417    fn test_gen_long_string() {
418        assert_eq!(
419            test_gen!(&mut [0, 0, 0, 0][..], gen_long_string, &[]),
420            Ok((vec![0, 0, 0, 0], 4))
421        );
422        assert_eq!(
423            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_long_string, b"test"),
424            Ok((vec![0, 0, 0, 4, 116, 101, 115, 116], 8))
425        );
426    }
427
428    #[test]
429    fn test_gen_field_array() {
430        assert_eq!(
431            test_gen!(
432                &mut [0, 0, 0, 0][..],
433                gen_field_array,
434                &FieldArray::default()
435            ),
436            Ok((vec![0, 0, 0, 0], 4))
437        );
438        assert_eq!(
439            test_gen!(
440                &mut [0, 0, 0, 0, 0, 0][..],
441                gen_field_array,
442                &vec![AMQPValue::Boolean(true)].into()
443            ),
444            Ok((vec![0, 0, 0, 2, 116, 1], 6))
445        );
446    }
447
448    #[test]
449    fn test_gen_timestamp() {
450        assert_eq!(
451            test_gen!(&mut [0, 0, 0, 0, 0, 0, 0, 0][..], gen_timestamp, 0),
452            Ok((vec![0, 0, 0, 0, 0, 0, 0, 0], 8))
453        );
454        assert_eq!(
455            test_gen!(
456                &mut [0, 0, 0, 0, 0, 0, 0, 0][..],
457                gen_timestamp,
458                18446744073709551615
459            ),
460            Ok((vec![255, 255, 255, 255, 255, 255, 255, 255], 8))
461        );
462    }
463
464    #[test]
465    fn test_gen_field_table() {
466        let mut table = FieldTable::default();
467        table.insert("test".into(), AMQPValue::Float(42.42));
468        table.insert("test2".into(), AMQPValue::Boolean(false));
469        assert_eq!(
470            test_gen!(
471                &mut [0, 0, 0, 0][..],
472                gen_field_table,
473                &FieldTable::default()
474            ),
475            Ok((vec![0, 0, 0, 0], 4))
476        );
477        assert_eq!(
478            test_gen!(
479                &mut [
480                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
481                ][..],
482                gen_field_table,
483                &table
484            ),
485            Ok((
486                vec![
487                    0, 0, 0, 18, 4, 116, 101, 115, 116, 102, 66, 41, 174, 20, 5, 116, 101, 115,
488                    116, 50, 116, 0
489                ],
490                22
491            ))
492        );
493    }
494
495    #[test]
496    fn test_gen_byte_array() {
497        assert_eq!(
498            test_gen!(&mut [0, 0, 0, 0][..], gen_byte_array, &ByteArray::default()),
499            Ok((vec![0, 0, 0, 0], 4))
500        );
501        assert_eq!(
502            test_gen!(
503                &mut [0, 0, 0, 0, 0, 0, 0, 0][..],
504                gen_byte_array,
505                &vec![42, 1, 2, 3].into()
506            ),
507            Ok((vec![0, 0, 0, 4, 42, 1, 2, 3], 8))
508        );
509    }
510
511    #[test]
512    fn test_gen_flags() {
513        let mut flags = AMQPFlags::default();
514        flags.add_flag("a".to_string(), true);
515        flags.add_flag("b".to_string(), false);
516        flags.add_flag("c".to_string(), true);
517        flags.add_flag("d".to_string(), true);
518        assert_eq!(
519            test_gen!(&mut [0][..], gen_flags, &flags),
520            Ok((vec![0b00001101], 1))
521        );
522        flags.add_flag("e".to_string(), true);
523        flags.add_flag("f".to_string(), false);
524        flags.add_flag("g".to_string(), true);
525        flags.add_flag("h".to_string(), true);
526        flags.add_flag("i".to_string(), false);
527        flags.add_flag("j".to_string(), true);
528        assert_eq!(
529            test_gen!(&mut [0, 0][..], gen_flags, &flags),
530            Ok((vec![0b11011101, 0b00000010], 2))
531        );
532    }
533}