use crate::error::DecodeError;
use crate::reading::Reading;
use crate::value::Value;
const fn frozen_header_size<V: Value>() -> usize {
4 + 2 + V::BYTES
}
#[must_use = "decoding returns readings that should be used"]
pub fn decode_frozen<V: Value, const INTERVAL: u16>(buf: &[u8]) -> Result<Vec<Reading<V>>, DecodeError> {
let header_size = frozen_header_size::<V>();
if buf.len() < header_size {
if buf.is_empty() {
return Ok(Vec::new());
}
return Err(DecodeError::BufferTooShort { expected: header_size, actual: buf.len() });
}
let base_ts = read_u32_le(buf, 0)?;
let count = read_u16_le(buf, 4)? as usize;
let first_value = V::read_le(&buf[6..]).to_i32();
if count == 0 {
return Ok(Vec::new());
}
let interval = u32::from(INTERVAL);
let mut result = Vec::with_capacity(count);
result.push(Reading { ts: base_ts, value: V::from_i32(first_value) });
if count == 1 {
return Ok(result);
}
let data = &buf[header_size..];
let mut reader = BitReader::new(data);
decode_bitstream::<V>(&mut reader, &mut result, base_ts, interval, count, first_value)?;
Ok(result)
}
#[inline]
pub(crate) fn decode_bitstream<V: Value>(
reader: &mut BitReader<'_>,
result: &mut Vec<Reading<V>>,
base_ts: u32,
interval: u32,
count: usize,
first_value: i32,
) -> Result<(), DecodeError> {
let mut prev_val = first_value;
let mut idx = 1u32;
while result.len() < count && reader.has_more() {
let ts = compute_ts(base_ts, idx, interval)?;
if reader.read_bits(1) == 0 {
result.push(Reading { ts, value: V::from_i32(prev_val) });
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
continue;
}
if reader.read_bits(1) == 0 {
let delta = if reader.read_bits(1) == 0 { 1 } else { -1 };
prev_val = prev_val.checked_add(delta).ok_or(DecodeError::MalformedData)?;
result.push(Reading { ts, value: V::from_i32(prev_val) });
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
continue;
}
if reader.read_bits(1) == 0 {
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
continue;
}
if reader.read_bits(1) == 0 {
let delta = if reader.read_bits(1) == 0 { 2 } else { -2 };
prev_val = prev_val.checked_add(delta).ok_or(DecodeError::MalformedData)?;
result.push(Reading { ts, value: V::from_i32(prev_val) });
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
continue;
}
if reader.read_bits(1) == 0 {
let run_len = (reader.read_bits(4) + 8).min((count - result.len()) as u32);
let mut ts = compute_ts(base_ts, idx, interval)?;
for _ in 0..run_len {
result.push(Reading { ts, value: V::from_i32(prev_val) });
ts = ts.checked_add(interval).ok_or(DecodeError::MalformedData)?;
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
}
continue;
}
if reader.read_bits(1) == 0 {
let run_len = (reader.read_bits(7) + 22).min((count - result.len()) as u32);
let mut ts = compute_ts(base_ts, idx, interval)?;
for _ in 0..run_len {
result.push(Reading { ts, value: V::from_i32(prev_val) });
ts = ts.checked_add(interval).ok_or(DecodeError::MalformedData)?;
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
}
continue;
}
if reader.read_bits(1) == 0 {
let e = reader.read_bits(4) as i32;
let delta = if e < 8 { e - 10 } else { e - 5 };
prev_val = prev_val.checked_add(delta).ok_or(DecodeError::MalformedData)?;
result.push(Reading { ts, value: V::from_i32(prev_val) });
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
continue;
}
if reader.read_bits(1) == 0 {
let raw = reader.read_bits(11);
let delta = if raw & 0x400 != 0 { (raw | 0xFFFF_F800) as i32 } else { raw as i32 };
prev_val = prev_val.checked_add(delta).ok_or(DecodeError::MalformedData)?;
result.push(Reading { ts, value: V::from_i32(prev_val) });
idx = idx.checked_add(1).ok_or(DecodeError::MalformedData)?;
} else {
let gap = reader.read_bits(6).saturating_add(2);
idx = idx.checked_add(gap).ok_or(DecodeError::MalformedData)?;
}
}
Ok(())
}
#[inline]
fn compute_ts(base_ts: u32, idx: u32, interval: u32) -> Result<u32, DecodeError> {
let offset = idx.checked_mul(interval).ok_or(DecodeError::MalformedData)?;
base_ts.checked_add(offset).ok_or(DecodeError::MalformedData)
}
#[inline]
fn read_u16_le(buf: &[u8], offset: usize) -> Result<u16, DecodeError> {
let end = offset.saturating_add(2);
if end > buf.len() {
return Err(DecodeError::BufferTooShort { expected: end, actual: buf.len() });
}
Ok(u16::from_le_bytes([buf[offset], buf[offset + 1]]))
}
#[inline]
fn read_u32_le(buf: &[u8], offset: usize) -> Result<u32, DecodeError> {
let end = offset.saturating_add(4);
if end > buf.len() {
return Err(DecodeError::BufferTooShort { expected: end, actual: buf.len() });
}
Ok(u32::from_le_bytes([buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]]))
}
pub(crate) struct BitReader<'a> {
buf: &'a [u8],
pos: usize,
bits: u64,
left: u32,
}
impl<'a> BitReader<'a> {
#[inline]
pub fn new(buf: &'a [u8]) -> Self {
let mut r = Self { buf, pos: 0, bits: 0, left: 0 };
r.refill();
r
}
#[inline]
fn refill(&mut self) {
if self.left == 0 && self.pos + 8 <= self.buf.len() {
let bytes: [u8; 8] = self.buf[self.pos..self.pos + 8].try_into().unwrap();
self.bits = u64::from_be_bytes(bytes);
self.pos += 8;
self.left = 64;
return;
}
while self.left <= 56 && self.pos < self.buf.len() {
self.bits = (self.bits << 8) | u64::from(self.buf[self.pos]);
self.pos += 1;
self.left += 8; }
}
#[inline]
pub fn read_bits(&mut self, n: u32) -> u32 {
debug_assert!(n <= 32, "cannot read more than 32 bits at a time");
if self.left < n { self.refill(); }
if self.left < n { return 0; }
self.left -= n;
((self.bits >> self.left) & ((1u64 << n) - 1)) as u32
}
#[inline]
pub fn has_more(&self) -> bool {
self.left > 0 || self.pos < self.buf.len()
}
}