use otspec::types::*;
use otspec::{
DeserializationError, Deserializer, ReaderContext, SerializationError, Serialize, Serializer,
};
#[derive(Debug, PartialEq)]
pub struct PackedDeltas(pub Vec<int16>);
const DELTAS_ARE_WORDS: u8 = 0x40;
const DELTAS_ARE_ZERO: u8 = 0x80;
const DELTA_RUN_COUNT_MASK: u8 = 0x3f;
#[allow(dead_code)] pub fn from_bytes(
c: &mut ReaderContext,
num_points: usize,
) -> Result<PackedDeltas, DeserializationError> {
let mut res = vec![];
while res.len() < num_points {
let control_byte: u8 = c.de()?;
let deltas_are_words = (control_byte & DELTAS_ARE_WORDS) > 0;
let run_count = (control_byte & DELTA_RUN_COUNT_MASK) + 1;
let deltas: Vec<i16>;
if control_byte & DELTAS_ARE_ZERO > 0 {
deltas = std::iter::repeat(0).take(run_count as usize).collect();
} else if deltas_are_words {
deltas = c.de_counted(run_count.into())?;
} else {
let delta_bytes: Vec<i8> = c.de_counted(run_count.into())?;
deltas = delta_bytes.iter().map(|x| *x as i16).collect();
}
res.extend(deltas);
}
Ok(PackedDeltas(res))
}
impl Serialize for PackedDeltas {
fn to_bytes(&self, data: &mut Vec<u8>) -> Result<(), SerializationError> {
let mut pos = 0;
let deltas = &self.0;
while pos < deltas.len() {
let mut value = deltas[pos];
if value == 0 {
let mut run_length = 0;
while pos < deltas.len() && deltas[pos] == 0 {
run_length += 1;
pos += 1;
}
while run_length >= 64 {
data.put(DELTAS_ARE_ZERO | 63_u8)?;
run_length -= 64;
}
if run_length > 0 {
data.put((DELTAS_ARE_ZERO | (run_length - 1)) as u8)?;
}
} else if (-128..=127).contains(&value) {
let mut start_of_run = pos;
while pos < deltas.len() {
value = deltas[pos];
if !(-128..=127).contains(&value) {
break;
}
if value == 0 && pos + 1 < deltas.len() && deltas[pos + 1] == 0 {
break;
}
pos += 1;
}
let mut run_length = pos - start_of_run;
while run_length >= 64 {
data.put(63_u8)?;
data.put(
deltas[start_of_run..start_of_run + 64]
.iter()
.map(|x| *x as i8)
.collect::<Vec<i8>>(),
)?;
start_of_run += 64;
run_length -= 64;
}
if run_length > 0 {
data.put((run_length - 1) as u8)?;
data.put(
deltas[start_of_run..pos]
.iter()
.map(|x| *x as i8)
.collect::<Vec<i8>>(),
)?;
}
} else {
let mut start_of_run = pos;
while pos < deltas.len() {
value = deltas[pos];
if value == 0 {
break;
}
if (-128..=127).contains(&value)
&& pos + 1 < deltas.len()
&& (-128..=127).contains(&deltas[pos + 1])
{
break;
}
pos += 1;
}
let mut run_length = pos - start_of_run;
while run_length >= 64 {
data.put(DELTAS_ARE_WORDS | 63)?;
for d in deltas[start_of_run..(start_of_run + 64)].iter() {
data.put(d)?;
}
start_of_run += 64;
run_length -= 64;
}
if run_length > 0 {
data.put(DELTAS_ARE_WORDS | (run_length - 1) as u8)?;
for d in deltas[start_of_run..pos].iter() {
data.put(d)?
}
}
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::otvar::packeddeltas::from_bytes;
use crate::otvar::packeddeltas::PackedDeltas;
use otspec::ReaderContext;
#[test]
fn test_packed_delta_de() {
let packed = vec![
0x03, 0x0a, 0x97, 0x00, 0xc6, 0x87, 0x41, 0x10, 0x22, 0xfb, 0x34,
];
let expected = PackedDeltas(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
let deserialized: PackedDeltas = from_bytes(&mut ReaderContext::new(packed), 14).unwrap();
assert_eq!(deserialized, expected);
}
#[test]
fn test_packed_delta_ser() {
let expected = vec![
0x03, 0x0a, 0x97, 0x00, 0xc6, 0x87, 0x41, 0x10, 0x22, 0xfb, 0x34,
];
let object = PackedDeltas(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
let serialized = otspec::ser::to_bytes(&object).unwrap();
assert_eq!(serialized, expected);
}
#[test]
fn test_packed_delta_66_zeros_ser() {
let expected = vec![0xbf, 0x81];
let object = PackedDeltas(std::iter::repeat(0).take(66).collect());
let serialized = otspec::ser::to_bytes(&object).unwrap();
assert_eq!(serialized, expected);
}
#[test]
fn test_packed_delta_66_words_ser() {
let expected = vec![
0x7f, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01, 0x90, 0x01,
0x90, 0x01, 0x90, 0x41, 0x01, 0x90, 0x01, 0x90,
];
let object = PackedDeltas(std::iter::repeat(400).take(66).collect());
let serialized = otspec::ser::to_bytes(&object).unwrap();
assert_eq!(serialized, expected);
}
#[test]
fn test_long_bytes_ser() {
let expected: Vec<u8> = vec![
0x3f, 0xf7, 0xef, 0x07, 0x20, 0x0d, 0x0c, 0x0d, 0x20, 0x0f, 0xf6, 0xef, 0xfd, 0x22,
0x0f, 0x0e, 0x0f, 0x22, 0x05, 0xf5, 0xf0, 0xf5, 0x08, 0x20, 0x1c, 0x22, 0xe4, 0xdf,
0xe3, 0xf6, 0x0e, 0x0a, 0x0f, 0x03, 0xe0, 0xf4, 0xf4, 0xf4, 0xe0, 0xfb, 0x09, 0x10,
0x03, 0xde, 0xf2, 0xf2, 0xf2, 0xde, 0xfb, 0x0b, 0x10, 0x0c, 0xf9, 0xe2, 0xe5, 0xdf,
0x1c, 0x22, 0x1e, 0x0b, 0xf2, 0xf7, 0xe5, 0xdd, 0x1c, 0x01, 0x24, 0xe5, 0x83,
];
let object = PackedDeltas(vec![
-9, -17, 7, 32, 13, 12, 13, 32, 15, -10, -17, -3, 34, 15, 14, 15, 34, 5, -11, -16, -11,
8, 32, 28, 34, -28, -33, -29, -10, 14, 10, 15, 3, -32, -12, -12, -12, -32, -5, 9, 16,
3, -34, -14, -14, -14, -34, -5, 11, 16, 12, -7, -30, -27, -33, 28, 34, 30, 11, -14, -9,
-27, -35, 28, 36, -27, 0, 0, 0, 0,
]);
let serialized = otspec::ser::to_bytes(&object).unwrap();
assert_eq!(serialized, expected);
}
}