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