1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
extern crate byteorder;
use std::io::Read;
use std::io::Write;
use std::collections::HashMap;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
fn as_aligned(i: u16) -> u16 {
let remainder = i % 4;
if remainder == 0 {
i
} else {
4 - remainder
}
}
pub fn encode(hm: &HashMap<u16, String>) -> Vec<u8> {
let vec = Vec::with_capacity(hm.len() * 2);
let mut buf = std::io::BufWriter::new(vec);
for (k, v) in hm.iter() {
buf.write_u16::<BigEndian>(*k).unwrap();
let write_length = v.len() as u16;
buf.write_u16::<BigEndian>(write_length).unwrap();
buf.write(v.as_bytes()).unwrap();
let align = as_aligned(write_length);
if align != 0 {
buf.write(vec![0; align as usize].as_slice()).unwrap();
}
};
buf.into_inner().unwrap()
}
pub fn decode<T: std::io::BufRead>(mut buf: &mut T) -> Result<HashMap<u16, String>, std::io::Error> {
let mut attrs = HashMap::new();
while let Ok(attr_type) = buf.read_u16::<BigEndian>() {
let length = try!(buf.read_u16::<BigEndian>());
let align = as_aligned(length);
{
let mut value_rdr = buf.take(length as u64);
let mut value_vec = &mut Vec::with_capacity(length as usize);
try!(value_rdr.read_to_end(value_vec));
attrs.insert(attr_type, String::from_utf8(value_vec.to_owned()).expect("Invalid UTF8"));
};
buf.consume(align as usize);
}
Ok(attrs)
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
use std::collections::HashMap;
#[test]
fn test_decode_tlv() {
let attrs_raw = vec![0, 6, 0, 5, 72, 101, 108, 108, 111, 0, 0, 0, 0, 6, 0, 5, 72, 101, 108, 108, 111, 0, 0, 0];
let rdr = &mut Cursor::new(attrs_raw);
match decode(rdr) {
Ok(m) => {
assert_eq!(m.len(), 1);
match m.get(&6) {
Some(v) => assert_eq!(v.to_string(), "Hello".to_string()),
None => assert_eq!(false, true)
}
},
Err(err) =>
println!("{:?}:", err)
}
}
#[test]
fn test_encode_tlv() {
let attrs_raw = vec![0, 6, 0, 5, 72, 101, 108, 108, 111, 0, 0, 0];
let mut hm = HashMap::new();
hm.insert(6 as u16, "Hello".to_string());
assert_eq!(encode(&hm), attrs_raw);
}
#[test]
fn test_encode_decode_tlv() {
let mut hm = HashMap::new();
hm.insert(6 as u16, "Hello".to_string());
let encoded = &mut Cursor::new(encode(&hm));
assert_eq!(hm, decode(encoded).unwrap());
}
}