caraspace/
serialization.rs

1//! (De)serialization methods
2//!
3//!
4
5use crate::errors::CRSerializationError;
6
7/// Search for a u16 bytemarker in a stream.
8///
9/// E.g. This can be an 0xAAAA indicator as a packet delimiter
10///
11/// # Arguments:
12///  
13///  * marker     : The marker to search for. Currently, only 
14///                 16bit markers are supported
15///  * bytestream : The stream to search the number in
16///  * start_pos  : Start searching from this position in 
17///                 the stream
18pub fn seek_marker<T: AsRef<[u8]>>(stream : &T, marker : u16, start_pos :usize) 
19  -> Result<usize, CRSerializationError> {
20  // -2 bc later on we are looking for 2 bytes!
21  let bytestream = stream.as_ref();
22  if bytestream.len() == 0 {
23    error!("Stream empty!");
24    return Err(CRSerializationError::StreamTooShort);
25  }
26  if start_pos  > bytestream.len() - 2 {
27    error!("Start position {} beyond stream capacity {}!", start_pos, bytestream.len() -2);
28    return Err(CRSerializationError::StreamTooShort);
29  }
30  let mut pos = start_pos;
31  let mut two_bytes : [u8;2]; 
32  // will find the next header
33  two_bytes = [bytestream[pos], bytestream[pos + 1]];
34  // FIXME - this should be little endian?
35  if u16::from_le_bytes(two_bytes) == marker {
36    return Ok(pos);
37  }
38  // if it is not at start pos, then traverse 
39  // the stream
40  pos += 1;
41  let mut found = false;
42  // we search for the next packet
43  for n in pos..bytestream.len() - 1 {
44    two_bytes = [bytestream[n], bytestream[n + 1]];
45    if (u16::from_le_bytes(two_bytes)) == marker {
46      pos = n;
47      found = true;
48      break;
49    }
50  }
51  if !found {
52    let delta = bytestream.len() - start_pos;
53    warn!("Can not find {} in bytestream [-{}:{}]!", marker, delta ,bytestream.len());
54    return Err(CRSerializationError::ValueNotFound);
55  }
56  trace!("Found {marker} at {pos}");
57  Ok(pos)
58}
59
60///// Encode/decode structs to `Vec::<u8>` to write to a file or
61///// send over the network
62/////
63pub trait CRSerializeable {
64
65  const CRHEAD: u16 = 0xAAAA;
66  const CRTAIL: u16 = 0x5555;
67  /// The SIZE is the size of the serialized 
68  /// bytestream INCLUDING 4 bytes for head
69  /// and tail bytes. In case the struct does 
70  /// NOT HAVE a fixed size, SIZE will be 0
71  /// (so default value of the trait
72  const CRSIZE: usize = 0;
73
74  /// Verify that the serialized representation of the struct has the 
75  /// correct size, including header + footer.
76  ///
77  /// Will panic for variable sized structs.
78  fn verify_fixed(stream : &Vec<u8>, 
79                  pos    : &mut usize) -> Result<(), CRSerializationError> {
80    if !Self::CRSIZE == 0 {
81      // we can panic here, since this is a conceptional logic error. If we
82      // don't panic, monsters will arise downstream.
83      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!");
84    }
85    let head_pos = seek_marker(stream, Self::CRHEAD, *pos)?; 
86    let tail_pos = seek_marker(stream, Self::CRTAIL,  head_pos + Self::CRSIZE-2)?;
87    // At this state, this can be a header or a full event. Check here and
88    // proceed depending on the options
89    if tail_pos + 2 - head_pos != Self::CRSIZE {
90      error!("Seing {} bytes, but expecting {}", tail_pos + 2 - head_pos, Self::CRSIZE);
91      *pos = head_pos + 2; 
92      return Err(CRSerializationError::WrongByteSize);
93    }
94    *pos = head_pos + 2;
95    Ok(())
96  } 
97
98  /// Decode a serializable from a bytestream  
99  fn deserialize(bytestream : &Vec<u8>, 
100                     pos        : &mut usize)
101    -> Result<Self, CRSerializationError>
102    where Self : Sized;
103  
104  /// Encode a serializable to a bytestream  
105  fn serialize(&self) -> Vec<u8>;
106
107  ///// Decode a serializable directly from a TofPacket
108  //fn from_sclerite(sclerite : &Sclerite, name : String)
109  //  -> Result<Self, CRSerializationError>
110  //  where Self: Sized {
111  //  let s_object = sclerite.get(name)?;
112  //  let unpacked = Self::deserialize(&sclerite.payload, &mut 0)?;
113  //  Ok(unpacked)
114  //}
115//
116//
117//  fn from_slice(_slice     : &[u8],
118//                _start_pos : usize)
119//    -> Result<Self, CRSerializationError>
120//    where Self : Sized {
121//    println!("There can't be a default implementation for this trait!");
122//    todo!();
123//    }
124//
125//  /// Construct byte slice out of self.
126//  ///
127//  /// Can not fail.
128//  fn to_slice(&self) 
129//    -> &[u8]
130//    where Self : Sized {
131//    println!("There can't be a default implementation for this trait!");
132//    todo!();
133//  }
134}
135
136#[test]
137fn test_seek_marker() {
138  // just test it two times - FIXME - use a better method
139  let mut bytestream = vec![1,2,3,0xAA, 0xAA, 5, 7];
140  let mut pos = seek_marker(&bytestream, 0xaaaa, 0).unwrap();
141  assert_eq!(pos, 3);
142  
143  bytestream = vec![1,2,3,244, 16, 32, 0xaa, 0xff, 5, 7];
144  // remember byte order in vectors
145  pos = seek_marker(&bytestream, 0xffaa, 1).unwrap();
146  assert_eq!(pos, 6);
147  
148  bytestream = vec![0xaa,0xaa,3,244, 16, 32, 0xAA, 0xFF, 5, 7];
149  pos = seek_marker(&bytestream, 0xaaaa, 0).unwrap();
150  assert_eq!(pos, 0);
151}
152
153
154//use half::f16;
155//
156//// re-exports
157//pub use crate::errors::CRSerializationError;
158//
159//use std::error::Error;
160//use std::path::Path;
161//
162//use std::collections::VecDeque;
163//
164//use crate::packets::{
165//  TofPacket,
166//  PacketType,
167//};
168//
169//
170//#[derive(Debug, Copy, Clone)]
171//pub struct f8(u8);
172//
173//impl f8 {
174//    // Convert from little-endian byte array to f8
175//    pub fn from_le_bytes(bytes: [u8; 1]) -> Self {
176//        f8(bytes[0])
177//    }
178//}
179//
180///// Convert a vector of u16 into a vector of u8
181/////
182///// The resulting vector has twice the number
183///// of entries of the original vector.
184///// This is useful, when serializing data 
185///// represented as u16, e.g. the waveforms.
186//pub fn u16_to_u8(vec_u16: &[u16]) -> Vec<u8> {
187//    vec_u16.iter()
188//        .flat_map(|&n| n.to_le_bytes().to_vec())
189//        .collect()
190//}
191//
192///// Restore a vector of u16 from a vector of u8
193/////
194///// This interpretes two following u8 as an u16
195///// Useful for deserialization of waveforms.
196//pub fn u8_to_u16(vec_u8: &[u8]) -> Vec<u16> {
197//    vec_u8.chunks_exact(2)
198//        .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
199//        .collect()
200//}
201//
202///// Restore a vector of u16 from a vector of u8
203/////
204///// This interpretes two following u8 as an u16
205///// Useful for deserialization of waveforms.
206///// Additionally it masks the first 2 bits 
207///// binary adding 0x3ff to each u16.
208//pub fn u8_to_u16_14bit(vec_u8: &[u8]) -> Vec<u16> {
209//    vec_u8.chunks_exact(2)
210//        .map(|chunk| 0x3fff & u16::from_le_bytes([chunk[0], chunk[1]]))
211//        .collect()
212//}
213//
214///// Restore a vector of u16 from a vector of u8, using the first 2 bits of each u16 
215///// to get channel/cell error bit information
216/////
217///// This interpretes two following u8 as an u16
218///// Useful for deserialization of waveforms.
219///// Additioanlly, it preserves the error bits
220/////
221///// # Arguments:
222/////
223///// # Returns:
224/////
225/////   `Vec<u16>`, ch_sync_err, cell_sync_err : if one of the error bits is
226/////                                            set, ch_sync_err or cell_sync_err
227/////                                            will be set to true
228//pub fn u8_to_u16_err_check(vec_u8: &[u8]) -> (Vec<u16>, bool, bool) {
229//    let mut ch_sync_err   = true;
230//    let mut cell_sync_err = true;
231//    let vec_u16 = vec_u8.chunks_exact(2)
232//        .map(|chunk| {
233//          let value     =  u16::from_le_bytes([chunk[0], chunk[1]]);
234//          ch_sync_err   = ch_sync_err   && (((0x8000 & value) >> 15) == 0x1); 
235//          cell_sync_err = cell_sync_err && (((0x4000 & value) >> 14) == 0x1) ;
236//          return 0x3fff & value;
237//        })
238//        .collect();
239//    (vec_u16, ch_sync_err, cell_sync_err)
240//}
241//
242//pub fn parse_u8(bs : &Vec::<u8>, pos : &mut usize) -> u8 {
243//  let value = u8::from_le_bytes([bs[*pos]]);
244//  *pos += 1;
245//  value
246//}
247//
248//pub fn parse_u8_deque(bs : &VecDeque::<u8>, pos : &mut usize) -> u8 {
249//  let value = u8::from_le_bytes([bs[*pos]]);
250//  *pos += 1;
251//  value
252//}
253//
254//
255///// Get u32 from a bytestream and move on the position marker
256/////
257///// # Arguments 
258/////
259///// * bs
260///// * pos 
261//pub fn parse_u16(bs : &Vec::<u8>, pos : &mut usize) -> u16 {
262//  let value = u16::from_le_bytes([bs[*pos], bs[*pos+1]]);
263//  *pos += 2;
264//  value
265//}
266//
267//// FIXME - make this a generic
268//pub fn parse_u16_deque(bs : &VecDeque::<u8>, pos : &mut usize) -> u16 {
269//  let value = u16::from_le_bytes([bs[*pos], bs[*pos+1]]);
270//  *pos += 2;
271//  value
272//}
273//
274///// BIG Endian version of parse_u32. NOT for botched event id decoding!
275///// Used for network communications
276//pub fn parse_u32_be(bs : &Vec::<u8>, pos : &mut usize) -> u32 {
277//  let value = u32::from_be_bytes([bs[*pos], bs[*pos+1], bs[*pos+2], bs[*pos+3]]);
278//  *pos += 4;
279//  value
280//}
281//
282//pub fn parse_u32(bs : &Vec::<u8>, pos : &mut usize) -> u32 {
283//  let value = u32::from_le_bytes([bs[*pos], bs[*pos+1], bs[*pos+2], bs[*pos+3]]);
284//  *pos += 4;
285//  value
286//}
287//
288//pub fn parse_u64(bs : &Vec::<u8>, pos : &mut usize) -> u64 {
289//  let value = u64::from_le_bytes([bs[*pos],   bs[*pos+1], bs[*pos+2], bs[*pos+3],
290//                                  bs[*pos+4], bs[*pos+5], bs[*pos+6], bs[*pos+7]]);
291//  *pos += 8;
292//  value
293//}
294//
295//#[cfg(not(target_arch="arm"))]
296//pub fn parse_usize(bs: &Vec::<u8>, pos: &mut usize) -> usize {
297//  let value: usize = usize::from_le_bytes([bs[*pos],bs[*pos + 1], bs[*pos + 2], bs[*pos + 3], 
298//    bs[*pos + 4], bs[*pos + 5], bs[*pos + 6], bs[*pos + 7],]);
299//  *pos += std::mem::size_of::<usize>();
300//  value
301//}
302//
303//#[cfg(target_arch="arm")]
304//pub fn parse_usize(bs: &Vec::<u8>, pos: &mut usize) -> usize {
305//  parse_u32(bs, pos) as usize
306//}
307//
308///// Get an u32 from a bytestream 
309/////
310///// This assumes an underlying representation of 
311///// an atomic unit of 16bit instead of 8.
312///// This is realized for the raw data stream
313///// from the readoutboards.
314//pub fn parse_u32_for_16bit_words(bs  : &Vec::<u8>,
315//                                 pos : &mut usize) -> u32 {
316//  
317//  let raw_bytes_4  = [bs[*pos + 2],
318//                      bs[*pos + 3],
319//                      bs[*pos    ],
320//                      bs[*pos + 1]];
321//  *pos += 4;
322//  u32::from_le_bytes(raw_bytes_4)
323//}
324//
325///// Get an 48bit number from a bytestream 
326/////
327///// This assumes an underlying representation of 
328///// an atomic unit of 16bit instead of 8.
329///// This is realized for the raw data stream
330///// from the readoutboards.
331//pub fn parse_u48_for_16bit_words(bs  : &Vec::<u8>,
332//                                 pos : &mut usize) -> u64 {
333//  
334//  let raw_bytes_8  = [0u8,
335//                      0u8,
336//                      bs[*pos + 4],
337//                      bs[*pos + 5],
338//                      bs[*pos + 2],
339//                      bs[*pos + 3],
340//                      bs[*pos    ],
341//                      bs[*pos + 1]];
342//  *pos += 6;
343//  u64::from_le_bytes(raw_bytes_8)
344//}
345//
346//pub fn parse_f8(bs: &Vec<u8>, pos: &mut usize) -> f8 {
347//  let value = f8::from_le_bytes([bs[*pos]]);
348//  *pos += 1;
349//  value
350//}
351//
352//pub fn parse_f16(bs : &Vec::<u8>, pos : &mut usize) -> f16 {
353//  let value = f16::from_le_bytes([bs[*pos], bs[*pos+1]]);
354//  *pos += 2;
355//  value
356//}
357//
358//pub fn parse_f32(bs : &Vec::<u8>, pos : &mut usize) -> f32 {
359//  let value = f32::from_le_bytes([bs[*pos],   bs[*pos+1],  
360//                                  bs[*pos+2], bs[*pos+3]]);
361//  *pos += 4;
362//  value
363//}
364//
365//pub fn parse_f64(bs : &Vec::<u8>, pos : &mut usize) -> f64 {
366//  let value = f64::from_le_bytes([bs[*pos],   bs[*pos+1],  
367//                                  bs[*pos+2], bs[*pos+3],
368//                                  bs[*pos+4], bs[*pos+5],
369//                                  bs[*pos+6], bs[*pos+7]]);
370//  *pos += 8;
371//  value
372//}
373//
374//pub fn parse_bool(bs : &Vec::<u8>, pos : &mut usize) -> bool {
375//  let value = u8::from_le_bytes([bs[*pos]]); 
376//  *pos += 1;
377//  value > 0
378//}
379//
380//pub fn get_json_from_file(filename : &Path)
381//    -> Result<String, Box<dyn Error>> {
382//  let file_content = std::fs::read_to_string(filename)?;
383//  let config = serde_json::from_str(&file_content)?;
384//  Ok(config)
385//}
386//
387//
388//
389//
390//
391//#[cfg(test)]
392//mod test_serialization {
393//  use crate::serialization::{search_for_u16,
394//                             u16_to_u8};
395//
396//  #[test]
397//  fn test_u16_to_u8_size_doubled() {
398//    let size = 1000usize;
399//    let data = vec![42u16;size];
400//    let data_u8 = u16_to_u8(data.as_slice());
401//    let data_u8_size = data_u8.len();
402//    let double_size  = 2*size;
403//    assert_eq!(data_u8_size, double_size);
404//    
405//  }
406//
407//  #[test]
408//  fn test_search_for_2_bytemarker() {
409//    // just test it two times - FIXME - use a better method
410//    let mut bytestream = vec![1,2,3,0xAA, 0xAA, 5, 7];
411//    let mut pos = search_for_u16(0xAAAA, &bytestream, 0).unwrap();
412//    assert_eq!(pos, 3);
413//    
414//    bytestream = vec![1,2,3,244, 16, 32, 0xaa, 0xff, 5, 7];
415//    pos = search_for_u16(65450, &bytestream, 1).unwrap();
416//    assert_eq!(pos, 6);
417//    
418//    bytestream = vec![0xaa,0xaa,3,244, 16, 32, 0xAA, 0xFF, 5, 7];
419//    pos = search_for_u16(0xaaaa, &bytestream, 0).unwrap();
420//    assert_eq!(pos, 0);
421//  }
422//}