use half::f16;
pub use crate::errors::SerializationError;
use std::error::Error;
use std::path::Path;
use std::collections::VecDeque;
use crate::packets::{
TofPacket,
PacketType,
};
pub fn u16_to_u8(vec_u16: &[u16]) -> Vec<u8> {
vec_u16.iter()
.flat_map(|&n| n.to_le_bytes().to_vec())
.collect()
}
pub fn u8_to_u16(vec_u8: &[u8]) -> Vec<u16> {
vec_u8.chunks_exact(2)
.map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
.collect()
}
pub fn u8_to_u16_14bit(vec_u8: &[u8]) -> Vec<u16> {
vec_u8.chunks_exact(2)
.map(|chunk| 0x3fff & u16::from_le_bytes([chunk[0], chunk[1]]))
.collect()
}
pub fn u8_to_u16_err_check(vec_u8: &[u8]) -> (Vec<u16>, bool, bool) {
let mut ch_sync_err = true;
let mut cell_sync_err = true;
let vec_u16 = vec_u8.chunks_exact(2)
.map(|chunk| {
let value = u16::from_le_bytes([chunk[0], chunk[1]]);
ch_sync_err = ch_sync_err && (((0x8000 & value) >> 15) == 0x1);
cell_sync_err = cell_sync_err && (((0x4000 & value) >> 14) == 0x1) ;
return 0x3fff & value;
})
.collect();
(vec_u16, ch_sync_err, cell_sync_err)
}
pub fn parse_u8(bs : &Vec::<u8>, pos : &mut usize) -> u8 {
let value = u8::from_le_bytes([bs[*pos]]);
*pos += 1;
value
}
pub fn parse_u8_deque(bs : &VecDeque::<u8>, pos : &mut usize) -> u8 {
let value = u8::from_le_bytes([bs[*pos]]);
*pos += 1;
value
}
pub fn parse_u16(bs : &Vec::<u8>, pos : &mut usize) -> u16 {
let value = u16::from_le_bytes([bs[*pos], bs[*pos+1]]);
*pos += 2;
value
}
pub fn parse_u16_be(bs : &Vec::<u8>, pos : &mut usize) -> u16 {
let value = u16::from_be_bytes([bs[*pos], bs[*pos+1]]);
*pos += 2;
value
}
pub fn parse_u16_deque(bs : &VecDeque::<u8>, pos : &mut usize) -> u16 {
let value = u16::from_le_bytes([bs[*pos], bs[*pos+1]]);
*pos += 2;
value
}
pub fn parse_u32_be(bs : &Vec::<u8>, pos : &mut usize) -> u32 {
let value = u32::from_be_bytes([bs[*pos], bs[*pos+1], bs[*pos+2], bs[*pos+3]]);
*pos += 4;
value
}
pub fn parse_u32(bs : &Vec::<u8>, pos : &mut usize) -> u32 {
let value = u32::from_le_bytes([bs[*pos], bs[*pos+1], bs[*pos+2], bs[*pos+3]]);
*pos += 4;
value
}
pub fn parse_u64(bs : &Vec::<u8>, pos : &mut usize) -> u64 {
let value = u64::from_le_bytes([bs[*pos], bs[*pos+1], bs[*pos+2], bs[*pos+3],
bs[*pos+4], bs[*pos+5], bs[*pos+6], bs[*pos+7]]);
*pos += 8;
value
}
#[cfg(not(target_arch="arm"))]
pub fn parse_usize(bs: &Vec::<u8>, pos: &mut usize) -> usize {
let value: usize = usize::from_le_bytes([bs[*pos],bs[*pos + 1], bs[*pos + 2], bs[*pos + 3],
bs[*pos + 4], bs[*pos + 5], bs[*pos + 6], bs[*pos + 7],]);
*pos += std::mem::size_of::<usize>();
value
}
#[cfg(target_arch="arm")]
pub fn parse_usize(bs: &Vec::<u8>, pos: &mut usize) -> usize {
parse_u32(bs, pos) as usize
}
pub fn parse_u32_for_16bit_words(bs : &Vec::<u8>,
pos : &mut usize) -> u32 {
let raw_bytes_4 = [bs[*pos + 2],
bs[*pos + 3],
bs[*pos ],
bs[*pos + 1]];
*pos += 4;
u32::from_le_bytes(raw_bytes_4)
}
pub fn parse_u48_for_16bit_words(bs : &Vec::<u8>,
pos : &mut usize) -> u64 {
let raw_bytes_8 = [0u8,
0u8,
bs[*pos + 4],
bs[*pos + 5],
bs[*pos + 2],
bs[*pos + 3],
bs[*pos ],
bs[*pos + 1]];
*pos += 6;
u64::from_le_bytes(raw_bytes_8)
}
pub fn parse_f16(bs : &Vec::<u8>, pos : &mut usize) -> f16 {
let value = f16::from_le_bytes([bs[*pos], bs[*pos+1]]);
*pos += 2;
value
}
pub fn parse_f32(bs : &Vec::<u8>, pos : &mut usize) -> f32 {
let value = f32::from_le_bytes([bs[*pos], bs[*pos+1],
bs[*pos+2], bs[*pos+3]]);
*pos += 4;
value
}
pub fn parse_f64(bs : &Vec::<u8>, pos : &mut usize) -> f64 {
let value = f64::from_le_bytes([bs[*pos], bs[*pos+1],
bs[*pos+2], bs[*pos+3],
bs[*pos+4], bs[*pos+5],
bs[*pos+6], bs[*pos+7]]);
*pos += 8;
value
}
pub fn parse_bool(bs : &Vec::<u8>, pos : &mut usize) -> bool {
let value = u8::from_le_bytes([bs[*pos]]);
*pos += 1;
value > 0
}
pub fn get_json_from_file(filename : &Path)
-> Result<String, Box<dyn Error>> {
let file_content = std::fs::read_to_string(filename)?;
let config = serde_json::from_str(&file_content)?;
Ok(config)
}
pub trait Packable {
const PACKET_TYPE : PacketType;
fn pack(&self) -> TofPacket
where Self: Serialization {
let mut tp = TofPacket::new();
tp.payload = self.to_bytestream();
tp.packet_type = Self::PACKET_TYPE;
tp
}
}
pub trait Serialization {
const HEAD: u16;
const TAIL: u16;
const SIZE: usize = 0;
fn verify_fixed(stream : &Vec<u8>,
pos : &mut usize) -> Result<(), SerializationError> {
if !Self::SIZE == 0 {
panic!("Self::verify_fixed can be only used for structs with a fixed size! In case you are convinced, that your struct has indeed a fixed size, please implement trait Serialization::SIZE with the serialized size in bytes including 4 bytes for header and footer!");
}
let head_pos = search_for_u16(Self::HEAD, stream, *pos)?;
let tail_pos = search_for_u16(Self::TAIL, stream, head_pos + Self::SIZE-2)?;
if tail_pos + 2 - head_pos != Self::SIZE {
error!("Seing {} bytes, but expecting {}", tail_pos + 2 - head_pos, Self::SIZE);
*pos = head_pos + 2;
return Err(SerializationError::WrongByteSize);
}
*pos = head_pos + 2;
Ok(())
}
fn from_bytestream(bytestream : &Vec<u8>,
pos : &mut usize)
-> Result<Self, SerializationError>
where Self : Sized;
fn from_tofpacket(packet : &TofPacket)
-> Result<Self, SerializationError>
where Self: Sized {
let unpacked = Self::from_bytestream(&packet.payload, &mut 0)?;
Ok(unpacked)
}
fn to_bytestream(&self) -> Vec<u8> {
println!("There can't be a default implementation for this trait!");
todo!();
}
fn from_slice(_slice : &[u8],
_start_pos : usize)
-> Result<Self, SerializationError>
where Self : Sized {
println!("There can't be a default implementation for this trait!");
todo!();
}
fn to_slice(&self)
-> &[u8]
where Self : Sized {
println!("There can't be a default implementation for this trait!");
todo!();
}
}
pub fn search_for_u16(number : u16, bytestream : &Vec<u8>, start_pos : usize)
-> Result<usize, SerializationError> {
if bytestream.len() == 0 {
error!("Stream empty!");
return Err(SerializationError::StreamTooShort);
}
if start_pos > bytestream.len() - 2 {
error!("Start position {} beyond stream capacity {}!", start_pos, bytestream.len() -2);
return Err(SerializationError::StreamTooShort);
}
let mut pos = start_pos;
let mut two_bytes : [u8;2];
two_bytes = [bytestream[pos], bytestream[pos + 1]];
if u16::from_le_bytes(two_bytes) == number {
return Ok(pos);
}
pos += 1;
let mut found = false;
for n in pos..bytestream.len() - 1 {
two_bytes = [bytestream[n], bytestream[n + 1]];
if (u16::from_le_bytes(two_bytes)) == number {
pos = n;
found = true;
break;
}
}
if !found {
let delta = bytestream.len() - start_pos;
warn!("Can not find {} in bytestream [-{}:{}]!", number, delta ,bytestream.len());
return Err(SerializationError::ValueNotFound);
}
trace!("Found {number} at {pos}");
Ok(pos)
}
#[cfg(test)]
mod test_serialization {
use crate::serialization::{search_for_u16,
u16_to_u8};
#[test]
fn test_u16_to_u8_size_doubled() {
let size = 1000usize;
let data = vec![42u16;size];
let data_u8 = u16_to_u8(data.as_slice());
let data_u8_size = data_u8.len();
let double_size = 2*size;
assert_eq!(data_u8_size, double_size);
}
#[test]
fn test_search_for_2_bytemarker() {
let mut bytestream = vec![1,2,3,0xAA, 0xAA, 5, 7];
let mut pos = search_for_u16(0xAAAA, &bytestream, 0).unwrap();
assert_eq!(pos, 3);
bytestream = vec![1,2,3,244, 16, 32, 0xaa, 0xff, 5, 7];
pos = search_for_u16(65450, &bytestream, 1).unwrap();
assert_eq!(pos, 6);
bytestream = vec![0xaa,0xaa,3,244, 16, 32, 0xAA, 0xFF, 5, 7];
pos = search_for_u16(0xaaaa, &bytestream, 0).unwrap();
assert_eq!(pos, 0);
}
}