1pub 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
13pub 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
27pub 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
53pub 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
60pub fn gen_type<W: Write>(t: AMQPType) -> impl SerializeFn<W> {
62 gen_short_short_uint(t.get_id() as ShortShortUInt)
63}
64
65pub fn gen_id<W: Write>(id: ShortUInt) -> impl SerializeFn<W> {
67 gen_short_uint(id)
68}
69
70pub fn gen_boolean<W: Write>(b: Boolean) -> impl SerializeFn<W> {
72 gen_short_short_uint(if b { 1 } else { 0 })
73}
74
75pub fn gen_short_short_int<W: Write>(i: ShortShortInt) -> impl SerializeFn<W> {
77 be_i8(i)
78}
79
80pub fn gen_short_short_uint<W: Write>(u: ShortShortUInt) -> impl SerializeFn<W> {
82 be_u8(u)
83}
84
85pub fn gen_short_int<W: Write>(i: ShortInt) -> impl SerializeFn<W> {
87 be_i16(i)
88}
89
90pub fn gen_short_uint<W: Write>(u: ShortUInt) -> impl SerializeFn<W> {
92 be_u16(u)
93}
94
95pub fn gen_long_int<W: Write>(i: LongInt) -> impl SerializeFn<W> {
97 be_i32(i)
98}
99
100pub fn gen_long_uint<W: Write>(u: LongUInt) -> impl SerializeFn<W> {
102 be_u32(u)
103}
104
105pub fn gen_long_long_int<W: Write>(i: LongLongInt) -> impl SerializeFn<W> {
107 be_i64(i)
108}
109
110pub fn gen_long_long_uint<W: Write>(u: LongLongUInt) -> impl SerializeFn<W> {
112 be_u64(u)
113}
114
115pub fn gen_float<W: Write>(f: Float) -> impl SerializeFn<W> {
117 be_f32(f)
118}
119
120pub fn gen_double<W: Write>(d: Double) -> impl SerializeFn<W> {
122 be_f64(d)
123}
124
125pub 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
130pub 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
142pub 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
151pub 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
158pub fn gen_timestamp<W: Write>(t: Timestamp) -> impl SerializeFn<W> {
160 gen_long_long_uint(t)
161}
162
163pub 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
176pub 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
185pub 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}