Skip to main content

gondola_core/io/
serialization.rs

1//! The following file is part of gaps-online-software and published 
2//! under the GPLv3 license
3
4use crate::prelude::*;
5
6pub use crate::io::caraspace::{
7  Frameable
8};
9
10/// Encode/decode structs to `Vec::<u8>` to write to a file or
11/// send over the network
12pub trait Serialization {
13
14  /// Byte marker to mark beginning of payload
15  const HEAD: u16 = 0xAAAA;
16  /// Byte marker to mark end of payload
17  const TAIL: u16 = 0x5555;
18  /// The SIZE is the size of the serialized 
19  /// bytestream INCLUDING 4 bytes for head
20  /// and tail bytes. In case the struct does 
21  /// NOT HAVE a fixed size, SIZE will be 0
22  /// (so default value of the trait
23  const SIZE: usize = 0;
24  
25  /// Guess the size of te packet. This can be a 
26  /// preformance issue if te offset position 
27  /// is far off
28  ///
29  /// This will not advance the pos marker!
30  fn guess_size(stream : &Vec<u8>,
31                pos    : usize,
32                offset : usize)
33      -> Result<(usize,usize,usize), SerializationError> {
34    let head_pos = seek_marker(stream, Self::HEAD, pos)?; 
35    let tail_pos = seek_marker(stream, Self::TAIL, pos+ offset)?;
36    Ok((tail_pos + 2 - head_pos, head_pos, tail_pos))
37  }
38
39  /// Verify that the serialized representation of the struct has the 
40  /// correct size, including header + footer.
41  ///
42  /// Will panic for variable sized structs.
43  fn verify_fixed(stream : &Vec<u8>, 
44                  pos    : &mut usize) -> Result<(), SerializationError> {
45    if !Self::SIZE == 0 {
46      // we can panic here, since this is a conceptional logic error. If we
47      // don't panic, monsters will arise downstream.
48      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!");
49    }
50    if stream.len() < Self::SIZE {
51      return Err(SerializationError::StreamTooShort);
52    }
53    let head_pos = seek_marker(stream, Self::HEAD, *pos)?; 
54    let tail_pos = seek_marker(stream, Self::TAIL, head_pos + Self::SIZE-2)?;
55    if tail_pos + 2 - head_pos != Self::SIZE {
56      *pos = head_pos + 2; 
57      let actual = tail_pos + 2 - head_pos;
58      error!("Seeing {} bytes between HEAD and TAIL, expecting {}", actual, Self::SIZE);
59      return Err(SerializationError::WrongByteSize);
60    }
61    *pos = head_pos + 2;
62    Ok(())
63  } 
64
65  /// Decode a serializable from a bytestream  
66  ///
67  /// # Arguments:
68  ///   * bytestream : bytes including the ones which should 
69  ///                  be decoded
70  ///   * pos        : first byte in the bytestream which is 
71  ///                  part of the expected payload
72  //fn from_bytestream<T: AsRef<[u8]>>(bytestream : T, 
73  fn from_bytestream(bytestream : &Vec<u8>,
74                     pos        : &mut usize)
75    -> Result<Self, SerializationError>
76    where Self : Sized;
77  
78  /// Decode a serializable from a bytestream. This provides 
79  /// an alternative method to get the packet. If not implemented,
80  /// it will be the same as from_bytestream.
81  ///
82  /// # Arguments:
83  ///   * bytestream : bytes including the ones which should 
84  ///                  be decoded
85  ///   * pos        : first byte in the bytestream which is 
86  ///                  part of the expected payload
87  fn from_bytestream_alt(bytestream : &Vec<u8>, 
88                         pos        : &mut usize)
89    -> Result<Self, SerializationError>
90    where Self : Sized {
91    Self::from_bytestream(bytestream, pos)
92  }
93
94  /// Encode a serializable to a bytestream  
95  /// 
96  /// This shall return a representation of the struct
97  /// in such a way that to_bytestream and from_bytestream
98  /// are inverse operations.
99  fn to_bytestream(&self) -> Vec<u8> {
100    error!("No default implementation for trait!");
101    return Vec::<u8>::new();
102  }
103}
104
105//---------------------------------------------------
106
107/// Search for a u16 bytemarker in a stream.
108///
109/// E.g. This can be an 0xAAAA indicator as a packet delimiter
110///
111/// # Arguments:
112///  
113///  * marker     : The marker to search for. Currently, only 
114///                 16bit markers are supported
115///  * bytestream : The stream to search the number in
116///  * start_pos  : Start searching from this position in 
117///                 the stream
118pub fn seek_marker<T: AsRef<[u8]>>(stream : &T, marker : u16, start_pos :usize) 
119  -> Result<usize, SerializationError> {
120  // -2 bc later on we are looking for 2 bytes!
121  let bytestream = stream.as_ref();
122  if bytestream.len() == 0 {
123    error!("Stream empty!");
124    return Err(SerializationError::StreamTooShort);
125  }
126  if start_pos  > bytestream.len() - 2 {
127    error!("Start position {} beyond stream capacity {}!", start_pos, bytestream.len() -2);
128    return Err(SerializationError::StreamTooShort);
129  }
130  let mut pos = start_pos;
131  let mut two_bytes : [u8;2]; 
132  // will find the next header
133  two_bytes = [bytestream[pos], bytestream[pos + 1]];
134  // FIXME - this should be little endian?
135  if u16::from_le_bytes(two_bytes) == marker {
136    return Ok(pos);
137  }
138  // if it is not at start pos, then traverse 
139  // the stream
140  pos += 1;
141  let mut found = false;
142  // we search for the next packet
143  for n in pos..bytestream.len() - 1 {
144    two_bytes = [bytestream[n], bytestream[n + 1]];
145    if (u16::from_le_bytes(two_bytes)) == marker {
146      pos = n;
147      found = true;
148      break;
149    }
150  }
151  if !found {
152    let delta = bytestream.len() - start_pos;
153    warn!("Can not find {} in bytestream [-{}:{}]!", marker, delta ,bytestream.len());
154    return Err(SerializationError::ValueNotFound);
155  }
156  trace!("Found {marker} at {pos}");
157  Ok(pos)
158}
159
160#[test]
161fn test_seek_marker() {
162  // just test it two times - FIXME - use a better method
163  let mut bytestream = vec![1,2,3,0xAA, 0xAA, 5, 7];
164  let mut pos = seek_marker(&bytestream, 0xaaaa, 0).unwrap();
165  assert_eq!(pos, 3);
166  
167  bytestream = vec![1,2,3,244, 16, 32, 0xaa, 0xff, 5, 7];
168  // remember byte order in vectors
169  pos = seek_marker(&bytestream, 0xffaa, 1).unwrap();
170  assert_eq!(pos, 6);
171  
172  bytestream = vec![0xaa,0xaa,3,244, 16, 32, 0xAA, 0xFF, 5, 7];
173  pos = seek_marker(&bytestream, 0xaaaa, 0).unwrap();
174  assert_eq!(pos, 0);
175}
176