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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use otspec::types::*;
use otspec::{
DeserializationError, Deserialize, Deserializer, ReaderContext, SerializationError, Serialize,
Serializer,
};
#[derive(Debug, PartialEq)]
pub struct PackedPoints {
pub points: Option<Vec<uint16>>,
}
impl Deserialize for PackedPoints {
fn from_bytes(c: &mut ReaderContext) -> Result<Self, DeserializationError> {
let count1_u8: u8 = c.de()?;
let mut count: u16 = count1_u8 as u16;
if count > 127 {
let count2: u8 = c.de()?;
count = (count & 0xff) << 8 | count2 as u16;
}
if count == 0 {
return Ok(PackedPoints { points: None });
}
let mut res = vec![];
while res.len() < count as usize {
let control_byte: u8 = c.de()?;
let points_are_words = (control_byte & 0x80) > 0;
let run_count = (control_byte & 0x7f) + 1;
let deltas: Vec<u16>;
if points_are_words {
deltas = c.de_counted(run_count.into())?;
} else {
let delta_bytes: Vec<u8> = c.de_counted(run_count.into())?;
deltas = delta_bytes.iter().map(|x| *x as u16).collect();
}
res.extend(deltas);
}
let cumsum: Vec<u16> = res
.iter()
.scan(0, |acc, &x| {
*acc += x;
Some(*acc)
})
.collect();
Ok(PackedPoints {
points: Some(cumsum),
})
}
}
impl Serialize for PackedPoints {
fn to_bytes(&self, data: &mut Vec<u8>) -> Result<(), SerializationError> {
if self.points.is_none() {
return data.put(0_u8);
}
let points = self.points.as_ref().unwrap();
let num_points = points.len() as uint16;
if num_points <= 0x80 {
data.put(num_points as u8)?;
} else {
data.put(num_points | 0x8000)?;
}
let mut pos = 0;
let mut last_value = 0;
while pos < points.len() {
let mut run: Vec<u8> = vec![0];
let mut use_bytes: Option<bool> = None;
while pos < points.len() && run.len() < 127 {
let current = points[pos];
let delta = current - last_value;
if use_bytes.is_none() {
use_bytes = Some((0..=0xff).contains(&delta));
}
if use_bytes.unwrap() && !(0..=0xff).contains(&delta) {
break;
}
if use_bytes.unwrap() {
run.push(delta as u8);
} else {
run.push((delta >> 8) as u8);
run.push((delta & 0xff) as u8);
}
last_value = current;
pos += 1;
}
if use_bytes.unwrap() {
run[0] = (run.len() as u8) - 2;
} else {
run[0] = (run.len() as u8 - 2) | 0x80;
}
data.put(run)?
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::otvar::PackedPoints;
#[test]
fn test_packed_point_de() {
let packed = vec![
0x0b, 0x0a, 0x00, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x02, 0x02, 0x02,
];
let expected = PackedPoints {
points: Some(vec![0, 3, 4, 7, 8, 11, 12, 15, 17, 19, 21]),
};
let deserialized: PackedPoints = otspec::de::from_bytes(&packed).unwrap();
assert_eq!(deserialized, expected);
}
#[test]
fn test_packed_point_ser() {
let expected = vec![
0x0b, 0x0a, 0x00, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x02, 0x02, 0x02,
];
let object = PackedPoints {
points: Some(vec![0, 3, 4, 7, 8, 11, 12, 15, 17, 19, 21]),
};
let serialized = otspec::ser::to_bytes(&object).unwrap();
assert_eq!(serialized, expected);
}
#[test]
fn test_packed_point_zero_ser() {
let expected = vec![0x01, 0x00, 0x00];
let object = PackedPoints {
points: Some(vec![0]),
};
let serialized = otspec::ser::to_bytes(&object).unwrap();
assert_eq!(serialized, expected);
}
}