amqpr_codec/frame/content_header/
encoder.rs

1use bytes::{BigEndian, BufMut};
2
3use super::{ContentHeaderPayload, Properties};
4use args::{AmqpString, FieldArgument};
5
6use std::collections::HashMap;
7
8const MIN_PAYLOAD_SIZE: usize = 14;
9
10pub fn encode_payload(payload: ContentHeaderPayload) -> Vec<u8> {
11    debug!("Start encoging conent header");
12
13    let mut dst = Vec::with_capacity(MIN_PAYLOAD_SIZE);
14
15    dst.put_u16::<BigEndian>(payload.class_id);
16    debug!("class : {}", payload.class_id);
17
18    // "weitht" field must be 0.
19    dst.put_u16::<BigEndian>(0);
20
21    dst.put_u64::<BigEndian>(payload.body_size);
22    debug!("body size : {}", payload.body_size);
23
24    // Encode property flags
25    let property_flags = property_flags(&payload.properties);
26    dst.put_u16::<BigEndian>(property_flags);
27    debug!("property flags : {}", property_flags);
28
29    // Encode property list
30    if property_flags != 0b_0000_0000_0000_0001 {
31        property_list(&payload.properties, &mut dst);
32    }
33
34    dst
35}
36
37
38fn property_flags(ps: &Properties) -> u16 {
39    0b_____1000000000000000 * ps.content_type.is_some() as u16 +
40        0b_0100000000000000 * ps.content_encoding.is_some() as u16 +
41        0b_0010000000000000 * ps.headers.is_some() as u16 +
42        0b_0001000000000000 * ps.delivery_mode.is_some() as u16 +
43        0b_0000100000000000 * ps.priority.is_some() as u16 +
44        0b_0000010000000000 * ps.correlation_id.is_some() as u16 +
45        0b_0000001000000000 * ps.reply_to.is_some() as u16 +
46        0b_0000000100000000 * ps.expiration.is_some() as u16 +
47        0b_0000000010000000 * ps.message_id.is_some() as u16 +
48        0b_0000000001000000 * ps.timestamp.is_some() as u16 +
49        0b_0000000000100000 * ps.type_.is_some() as u16 +
50        0b_0000000000010000 * ps.user_id.is_some() as u16 +
51        0b_0000000000001000 * ps.app_id.is_some() as u16 +
52
53        // No further properties.
54        0b_0000_0000_0000_0001
55}
56
57
58fn property_list(ps: &Properties, dst: &mut Vec<u8>) {
59    if let Some(ref s) = ps.content_type {
60        encode_short_str(s, dst);
61    }
62
63    if let Some(ref s) = ps.content_encoding {
64        encode_short_str(s, dst);
65    }
66
67    if let Some(ref f) = ps.headers {
68        encode_field_table(f, dst);
69    }
70
71    if let Some(ref o) = ps.delivery_mode {
72        dst.put_u8(*o);
73    }
74
75    if let Some(ref o) = ps.priority {
76        dst.put_u8(*o);
77    }
78
79    if let Some(ref s) = ps.correlation_id {
80        encode_short_str(s, dst);
81    }
82
83    if let Some(ref s) = ps.reply_to {
84        encode_short_str(s, dst);
85    }
86
87    if let Some(ref s) = ps.expiration {
88        encode_short_str(s, dst);
89    }
90
91    if let Some(ref s) = ps.message_id {
92        encode_short_str(s, dst);
93    }
94
95    if let Some(ref t) = ps.timestamp {
96        dst.put_i64::<BigEndian>(*t);
97    }
98
99    if let Some(ref s) = ps.type_ {
100        encode_short_str(s, dst);
101    }
102
103    if let Some(ref s) = ps.user_id {
104        encode_short_str(s, dst);
105    }
106
107    if let Some(ref s) = ps.app_id {
108        encode_short_str(s, dst);
109    }
110}
111
112
113fn encode_short_str(s: &AmqpString, dst: &mut Vec<u8>) {
114    dst.put_u8(s.len() as u8);
115    dst.put(s.as_bytes());
116}
117
118fn encode_field_table(f: &HashMap<AmqpString, FieldArgument>, dst: &mut Vec<u8>) {
119    ::frame::method::encoder::encode_field_table_0(f, dst);
120}