1use crate::rosmsg::RosMsg;
2use error_chain::bail;
3use std::collections::HashMap;
4use std::io::Error;
5
6pub fn decode<R: std::io::Read>(data: &mut R) -> Result<HashMap<String, String>, Error> {
7 RosMsg::decode(data)
8}
9
10pub fn encode<W: std::io::Write>(
11 writer: &mut W,
12 data: &HashMap<String, String>,
13) -> Result<(), Error> {
14 data.encode(writer)
15}
16
17pub fn match_field(
18 fields: &HashMap<String, String>,
19 field: &str,
20 expected: &str,
21) -> Result<(), super::error::Error> {
22 use super::error::ErrorKind;
23 let actual = match fields.get(field) {
24 Some(actual) => actual,
25 None => bail!(ErrorKind::HeaderMissingField(field.into())),
26 };
27 if actual != expected {
28 bail!(ErrorKind::HeaderMismatch(
29 field.into(),
30 expected.into(),
31 actual.clone(),
32 ));
33 }
34 Ok(())
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use std::collections::HashMap;
41
42 static FAILED_TO_ENCODE: &str = "Failed to encode";
43 static FAILED_TO_DECODE: &str = "Failed to decode";
44
45 #[test]
46 fn writes_empty_map() {
47 let mut cursor = std::io::Cursor::new(Vec::new());
48 let data = HashMap::<String, String>::new();
49 encode(&mut cursor, &data).expect(FAILED_TO_ENCODE);
50
51 assert_eq!(vec![0, 0, 0, 0], cursor.into_inner());
52 }
53
54 #[test]
55 fn writes_single_item() {
56 let mut cursor = std::io::Cursor::new(Vec::new());
57 let mut data = HashMap::<String, String>::new();
58 data.insert(String::from("abc"), String::from("123"));
59 encode(&mut cursor, &data).expect(FAILED_TO_ENCODE);
60 assert_eq!(
61 vec![11, 0, 0, 0, 7, 0, 0, 0, 97, 98, 99, 61, 49, 50, 51],
62 cursor.into_inner()
63 );
64 }
65
66 #[test]
67 fn writes_multiple_items() {
68 let mut cursor = std::io::Cursor::new(Vec::new());
69 let mut data = HashMap::<String, String>::new();
70 data.insert(String::from("abc"), String::from("123"));
71 data.insert(String::from("AAA"), String::from("B0"));
72 encode(&mut cursor, &data).expect(FAILED_TO_ENCODE);
73 let data = cursor.into_inner();
74 assert!(
75 vec![
76 21, 0, 0, 0, 7, 0, 0, 0, 97, 98, 99, 61, 49, 50, 51, 6, 0, 0, 0, 65, 65, 65, 61,
77 66, 48,
78 ] == data
79 || vec![
80 21, 0, 0, 0, 6, 0, 0, 0, 65, 65, 65, 61, 66, 48, 7, 0, 0, 0, 97, 98, 99, 61,
81 49, 50, 51,
82 ] == data
83 );
84 }
85
86 #[test]
87 fn reads_empty_map() {
88 let input = vec![0, 0, 0, 0];
89 let data = decode(&mut std::io::Cursor::new(input)).expect(FAILED_TO_DECODE);
90 assert_eq!(0, data.len());
91 }
92
93 #[test]
94 fn reads_single_element() {
95 let input = vec![11, 0, 0, 0, 7, 0, 0, 0, 97, 98, 99, 61, 49, 50, 51];
96 let data = decode(&mut std::io::Cursor::new(input)).expect(FAILED_TO_DECODE);
97 assert_eq!(1, data.len());
98 assert_eq!(Some(&String::from("123")), data.get("abc"));
99 }
100
101 #[test]
102 fn reads_typical_header() {
103 let input = vec![
104 0xb0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
105 0x65, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x73,
106 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x0a, 0x25, 0x00,
107 0x00, 0x00, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x69, 0x64, 0x3d, 0x2f, 0x72, 0x6f,
108 0x73, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f, 0x34, 0x37, 0x36, 0x37, 0x5f, 0x31, 0x33,
109 0x31, 0x36, 0x39, 0x31, 0x32, 0x37, 0x34, 0x31, 0x35, 0x35, 0x37, 0x0a, 0x00, 0x00,
110 0x00, 0x6c, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x3d, 0x31, 0x27, 0x00, 0x00,
111 0x00, 0x6d, 0x64, 0x35, 0x73, 0x75, 0x6d, 0x3d, 0x39, 0x39, 0x32, 0x63, 0x65, 0x38,
112 0x61, 0x31, 0x36, 0x38, 0x37, 0x63, 0x65, 0x63, 0x38, 0x63, 0x38, 0x62, 0x64, 0x38,
113 0x38, 0x33, 0x65, 0x63, 0x37, 0x33, 0x63, 0x61, 0x34, 0x31, 0x64, 0x31, 0x0e, 0x00,
114 0x00, 0x00, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x3d, 0x2f, 0x63, 0x68, 0x61, 0x74, 0x74,
115 0x65, 0x72, 0x14, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x74, 0x64,
116 0x5f, 0x6d, 0x73, 0x67, 0x73, 0x2f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
117 ];
118 let data = decode(&mut std::io::Cursor::new(input)).expect(FAILED_TO_DECODE);
119 assert_eq!(6, data.len());
120 assert_eq!(
121 Some(&String::from("string data\n\n")),
122 data.get("message_definition")
123 );
124 assert_eq!(
125 Some(&String::from("/rostopic_4767_1316912741557")),
126 data.get("callerid")
127 );
128 assert_eq!(Some(&String::from("1")), data.get("latching"));
129 assert_eq!(
130 Some(&String::from("992ce8a1687cec8c8bd883ec73ca41d1")),
131 data.get("md5sum")
132 );
133 assert_eq!(Some(&String::from("/chatter")), data.get("topic"));
134 assert_eq!(Some(&String::from("std_msgs/String")), data.get("type"));
135 }
136}