use serde;
use serde::ser::SerializeStruct;
use std::io::{Read, Seek, SeekFrom, Write};
use std::mem;
pub const FOOTER_SIZE: u64 = 12;
#[derive(Debug, Clone)]
pub struct Measurement {
pub time: u64,
pub data: String,
}
impl Measurement {
pub fn decode<S: Read + Seek>(storage: &mut S, offset: u64) -> Result<Measurement, ::Error> {
if offset < FOOTER_SIZE {
return Err(err_server!("invalid offset"));
}
let mut footer = vec![0u8; FOOTER_SIZE as usize];
storage.seek(SeekFrom::Start(offset - FOOTER_SIZE as u64))?;
storage.read_exact(&mut footer)?;
let mut time_encoded: [u8; 8] = Default::default();
time_encoded.copy_from_slice(&footer[4..12]);
let time = u64::from_le(unsafe { mem::transmute_copy(&time_encoded) });
let mut data_size_encoded: [u8; 4] = Default::default();
data_size_encoded.copy_from_slice(&footer[0..4]);
let data_size = u32::from_le(unsafe { mem::transmute_copy(&data_size_encoded) });
if offset < FOOTER_SIZE + data_size as u64 {
return Err(err_server!("invalid offset"));
}
let data_offset = offset - data_size as u64 - FOOTER_SIZE as u64;
let mut data = vec![0; data_size as usize];
storage.seek(SeekFrom::Start(data_offset))?;
storage.read_exact(&mut data)?;
let measurement = Measurement { time, data: String::from_utf8(data)? };
Ok(measurement)
}
pub fn encode<S: Write + Seek>(&self, storage: &mut S, offset: u64) -> Result<(), ::Error> {
let time_encoded: [u8; 8] = unsafe { mem::transmute(self.time.to_le()) };
let data_size_encoded: [u8; 4] =
unsafe { mem::transmute((self.data.len() as u32).to_le()) };
let mut encoded = self.data.clone().as_bytes().to_vec();
encoded.extend_from_slice(&data_size_encoded);
encoded.extend_from_slice(&time_encoded);
assert!(encoded.len() as u64 == self.get_encoded_size());
storage.seek(SeekFrom::Start(offset))?;
storage.write_all(&encoded)?;
Ok(())
}
pub fn get_encoded_size(&self) -> u64 {
(self.data.len() as u64 + FOOTER_SIZE) as u64
}
}
impl serde::Serialize for Measurement {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
let mut state = serializer.serialize_struct("Measurement", 2)?;
state.serialize_field("time", &self.time)?;
state.serialize_field("data", &self.data)?;
state.end()
}
}