gondola_core/io/
parsers.rs

1//! This file contains generic parsers to read data from a stream of 
2//! bytes and interpret them as various types.
3//!
4// This file is part of gaps-online-software and published 
5// under the GPLv3 license
6
7use crate::prelude::*;
8
9//// Luma's generic version - needs to be checked and benchmarked
10//pub fn parse_num<T, S>(stream: S, pos: &mut usize) -> T
11//where
12//    T: Copy + Default + Sized + FromBytes,
13//    S: AsRef<[u8]> {
14//    let bs = stream.as_ref();
15//    let mut buf = [0u8; size_of::<T>()];
16//    buf.copy_from_slice(&bs[*pos..*pos + size_of::<T>()]);
17//    *pos += size_of::<T>();
18//    T::from_le_bytes(buf)
19//}
20
21/// Get a u8 from a vector of bytes and advance 
22/// a position marker by 1
23pub fn parse_bool<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> bool {
24  let bs = stream.as_ref();
25  let value = u8::from_le_bytes([bs[*pos]]); 
26  *pos += 1;
27  value > 0
28}
29
30
31/// Get a u8 from a vector of bytes and advance 
32/// a position marker by 1
33pub fn parse_u8<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u8 {
34  let bs = stream.as_ref();
35  let value = u8::from_le_bytes([bs[*pos]]);
36  *pos += 1;
37  value
38}
39
40/// Get a u16 from a vector of bytes and advance 
41/// a position marker by 2
42///
43/// Note: written out as a generic here, TODO benchmark
44pub fn parse_u16<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u16 {
45  let bs = stream.as_ref();
46  let value = u16::from_le_bytes([bs[*pos], bs[*pos+1]]);
47  *pos += 2;
48  value
49}
50
51/// Get a u16 from a vector of bytes in big-endian and advance 
52/// a position marker by 2
53pub fn parse_u16_be<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u16 {
54  let bs = stream.as_ref();
55  let value = u16::from_be_bytes([bs[*pos], bs[*pos+1]]);
56  *pos += 2;
57  value
58}
59
60/// Get a u32 from a vector of bytes in big-endian and advance 
61/// a position marker by 4
62pub fn parse_u32_be<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u32 {
63  let bs = stream.as_ref();
64  let value = u32::from_be_bytes([bs[*pos], bs[*pos+1], bs[*pos+2], bs[*pos+3]]);
65  *pos += 4;
66  value
67}
68
69/// Get a u32 from a vector of bytes and advance 
70/// a position marker by 4
71pub fn parse_u32<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u32 {
72  let bs = stream.as_ref();
73  let value = u32::from_le_bytes([bs[*pos], bs[*pos+1], bs[*pos+2], bs[*pos+3]]);
74  *pos += 4;
75  value
76}
77
78/// Get a u64 from a vector of bytes and advance 
79/// a position marker by 8
80pub fn parse_u64<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u64 {
81  let bs = stream.as_ref();
82  let value = u64::from_le_bytes([bs[*pos],   bs[*pos+1], bs[*pos+2], bs[*pos+3],
83                                  bs[*pos+4], bs[*pos+5], bs[*pos+6], bs[*pos+7]]);
84  *pos += 8;
85  value
86}
87
88
89/// Get a u64 from a vector of bytes and advance 
90/// a position marker by 8
91pub fn parse_u64_old_for_test(bs : &Vec::<u8>, pos : &mut usize) -> u64 {
92  let value = u64::from_le_bytes([bs[*pos],   bs[*pos+1], bs[*pos+2], bs[*pos+3],
93                                  bs[*pos+4], bs[*pos+5], bs[*pos+6], bs[*pos+7]]);
94  *pos += 8;
95  value
96}
97
98#[deprecated(note = "Please use parse_u32 or parse_u64 explicitly, since the decoding of the bytestream is architecture independent!")]
99#[cfg(not(target_arch="arm"))]
100pub fn parse_usize(bs: &Vec::<u8>, pos: &mut usize) -> usize {
101  let value: usize = usize::from_le_bytes([bs[*pos],bs[*pos + 1], bs[*pos + 2], bs[*pos + 3], 
102    bs[*pos + 4], bs[*pos + 5], bs[*pos + 6], bs[*pos + 7],]);
103  *pos += std::mem::size_of::<usize>();
104  value
105}
106
107#[deprecated(note = "Please use parse_u32 or parse_u64 explicitly, since the decoding of the bytestream is architecture independent!")]
108#[cfg(target_arch="arm")]
109pub fn parse_usize(bs: &Vec::<u8>, pos: &mut usize) -> usize {
110  parse_u32(bs, pos) as usize
111}
112
113/// Get a string from a bytestream and advance a position marker
114/// 
115/// Warning, this is unsafe and might fail. It also expects that the 
116/// string is perfixed with a u16 containing its size.
117///
118/// # Arguments 
119///
120/// * bs     : Serialized data, stream of bytes
121/// * pos    : Position marker - start postion of 
122///            the deserialization
123pub fn parse_string<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> String {
124  let bs    = stream.as_ref();
125  let size  = parse_u16(stream, pos) as usize;
126  let s_string : Vec<u8> = bs[*pos..*pos + size].to_vec();
127  let value = String::from_utf8(s_string).unwrap();
128  *pos += size;
129  value
130}
131
132/// Get a u32 from a vector of bytes and advance
133/// a position marker by 4 for a non-standard 
134/// representation of u32 (neither le or be, but 
135/// shuffled)
136/// 
137/// <div class="warning">
138/// This assumes an underlying representation of 
139/// an atomic unit of 16bit instead of 8.
140/// This is a non-convetional byte respresentation
141/// for a u32 and needs to be used with care
142/// </div>
143pub fn parse_u32_for_16bit_words<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u32 {
144  let bs = stream.as_ref();
145  let raw_bytes_4  = [bs[*pos + 2],
146                      bs[*pos + 3],
147                      bs[*pos    ],
148                      bs[*pos + 1]];
149  *pos += 4;
150  u32::from_le_bytes(raw_bytes_4)
151}
152
153/// Get a 48bit number from a vector of bytes 
154///
155/// <div class="warning"> 48bit unsigned integer is a custom "type"!
156/// </div>
157///
158/// <div class="warning"> 
159/// This assumes an underlying representation of 
160/// an atomic unit of 16bit instead of 8.
161/// </div>
162pub fn parse_u48_for_16bit_words<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> u64 {
163  let bs = stream.as_ref();
164  let raw_bytes_8  = [0u8,
165                      0u8,
166                      bs[*pos + 4],
167                      bs[*pos + 5],
168                      bs[*pos + 2],
169                      bs[*pos + 3],
170                      bs[*pos    ],
171                      bs[*pos + 1]];
172  *pos += 6;
173  u64::from_le_bytes(raw_bytes_8)
174}
175
176/// Get a f16 from a vector of bytes and advance 
177/// a position marker by 2
178///
179/// <div class="warning"> f16 is called "half" and a non-common
180/// datatype which can dependent on the implementaion.
181/// The implementation used here is from the rust "half" crate
182/// </div>
183pub fn parse_f16<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> f16 {
184  let bs = stream.as_ref();
185  let value = f16::from_le_bytes([bs[*pos], bs[*pos+1]]);
186  *pos += 2;
187  value
188}
189
190/// Get a f32 from a vector of bytes and advance 
191/// a position marker by 4
192pub fn parse_f32<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> f32 {
193  let bs = stream.as_ref();
194  let value = f32::from_le_bytes([bs[*pos],   bs[*pos+1],  
195                                  bs[*pos+2], bs[*pos+3]]);
196  *pos += 4;
197  value
198}
199
200/// Get a f64 from a vector of bytes and advance 
201/// a position marker by 8
202pub fn parse_f64<T: AsRef<[u8]>>(stream : &T, pos : &mut usize) -> f64 {
203  let bs = stream.as_ref();
204  let value = f64::from_le_bytes([bs[*pos],   bs[*pos+1],  
205                                  bs[*pos+2], bs[*pos+3],
206                                  bs[*pos+4], bs[*pos+5],
207                                  bs[*pos+6], bs[*pos+7]]);
208  *pos += 8;
209  value
210}
211
212/// Restore a vector of u16 from a vector of u8
213///
214/// This interpretes two following u8 as an u16
215/// Useful for deserialization of waveforms.
216pub fn u8_to_u16(vec_u8: &[u8]) -> Vec<u16> {
217    vec_u8.chunks_exact(2)
218        .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
219        .collect()
220}
221
222/// This interpretes two following u8 as an u16
223/// Useful for deserialization of waveforms.
224/// Additionally it masks the first 2 bits 
225/// binary adding 0x3ff to each u16.
226pub fn u8_to_u16_14bit(vec_u8: &[u8]) -> Vec<u16> {
227    vec_u8.chunks_exact(2)
228        .map(|chunk| 0x3fff & u16::from_le_bytes([chunk[0], chunk[1]]))
229        .collect()
230}
231
232/// Restore a vector of u16 from a vector of u8, using the first 2 bits of each u16 
233/// to get channel/cell error bit information
234///
235/// This interpretes two following u8 as an u16
236/// Useful for deserialization of waveforms.
237/// Additioanlly, it preserves the error bits
238///
239/// # Arguments:
240///
241/// # Returns:
242///
243///   `Vec<u16>`, ch_sync_err, cell_sync_err : if one of the error bits is
244///                                            set, ch_sync_err or cell_sync_err
245///                                            will be set to true
246pub fn u8_to_u16_err_check(vec_u8: &[u8]) -> (Vec<u16>, bool, bool) {
247    let mut ch_sync_err   = true;
248    let mut cell_sync_err = true;
249    let vec_u16 = vec_u8.chunks_exact(2)
250        .map(|chunk| {
251          let value     =  u16::from_le_bytes([chunk[0], chunk[1]]);
252          ch_sync_err   = ch_sync_err   && (((0x8000 & value) >> 15) == 0x1); 
253          cell_sync_err = cell_sync_err && (((0x4000 & value) >> 14) == 0x1) ;
254          return 0x3fff & value;
255        })
256        .collect();
257    (vec_u16, ch_sync_err, cell_sync_err)
258}
259
260/// The resulting vector has twice the number
261/// of entries of the original vector.
262/// This is useful, when serializing data 
263/// represented as u16, e.g. the waveforms.
264pub fn u16_to_u8(vec_u16: &[u16]) -> Vec<u8> {
265    vec_u16.iter()
266        .flat_map(|&n| n.to_le_bytes().to_vec())
267        .collect()
268}
269
270//====================================================
271
272#[cfg(feature = "random")]
273#[test]
274fn test_parse_bool() {
275  #[cfg(feature="random")]
276  use rand::Rng;
277
278  let mut rng    = rand::rng();
279  let mut stream = Vec::<u8>::new();
280  let mut data   = Vec::<bool>::new();
281  for _ in 0..100 {
282    let test_byte  = rng.random::<bool>();
283    stream.push(test_byte as u8);
284    data.push(test_byte);
285  }
286  let mut pos = 0usize;
287  for k in 0..stream.len() {
288    assert_eq!(parse_bool(&stream, &mut pos), data[k]);
289  }
290}
291
292#[cfg(feature = "random")]
293#[test]
294fn test_parse_u8() {
295  #[cfg(feature="random")]
296  use rand::Rng;
297
298  let mut rng    = rand::rng();
299  let mut stream = Vec::<u8>::new();
300  let mut data   = Vec::<u8>::new();
301  for _ in 0..100 {
302    let test_byte  = rng.random::<u8>();
303    stream.push(test_byte);
304    data.push(test_byte);
305  }
306  let mut pos = 0usize;
307  for k in 0..stream.len() {
308    assert_eq!(parse_u8(&stream, &mut pos), data[k]);
309  }
310}
311
312#[cfg(feature = "random")]
313#[test]
314fn test_parse_u16() {
315  #[cfg(feature="random")]
316  use rand::Rng;
317
318  let mut rng    = rand::rng();
319  let mut stream = Vec::<u8>::new();
320  let mut data   = Vec::<u16>::new();
321  for _ in 0..100 {
322    let test_data  = rng.random::<u16>();
323    for k in test_data.to_le_bytes() {
324      stream.push(k);
325    }
326    data.push(test_data);
327  }
328  let mut pos = 0usize;
329  for k in data {
330    assert_eq!(parse_u16(&stream, &mut pos), k);
331  }
332}
333
334#[test]
335fn test_parse_u16_be() {
336  #[cfg(feature="random")]
337  use rand::Rng;
338
339  let mut rng    = rand::rng();
340  let mut stream = Vec::<u8>::new();
341  let mut data   = Vec::<u16>::new();
342  for _ in 0..100 {
343    let test_data  = rng.random::<u16>();
344    for k in test_data.to_be_bytes() {
345      stream.push(k);
346    }
347    data.push(test_data);
348  }
349  let mut pos = 0usize;
350  for k in data {
351    assert_eq!(parse_u16_be(&stream, &mut pos), k);
352  }
353}
354
355#[cfg(feature = "random")]
356#[test]
357fn test_parse_u32() {
358  #[cfg(feature="random")]
359  use rand::Rng;
360
361  let mut rng    = rand::rng();
362  let mut stream = Vec::<u8>::new();
363  let mut data   = Vec::<u32>::new();
364  for _ in 0..100 {
365    let test_data  = rng.random::<u32>();
366    for k in test_data.to_le_bytes() {
367      stream.push(k);
368    }
369    data.push(test_data);
370  }
371  let mut pos = 0usize;
372  for k in data {
373    assert_eq!(parse_u32(&stream, &mut pos), k);
374  }
375}
376
377#[test]
378fn test_parse_u32_be() {
379  #[cfg(feature="random")]
380  use rand::Rng;
381
382  let mut rng    = rand::rng();
383  let mut stream = Vec::<u8>::new();
384  let mut data   = Vec::<u32>::new();
385  for _ in 0..100 {
386    let test_data  = rng.random::<u32>();
387    for k in test_data.to_be_bytes() {
388      stream.push(k);
389    }
390    data.push(test_data);
391  }
392  let mut pos = 0usize;
393  for k in data {
394    assert_eq!(parse_u32_be(&stream, &mut pos), k);
395  }
396}
397
398#[cfg(feature = "random")]
399#[test]
400fn test_parse_u64() {
401  #[cfg(feature="random")]
402  use rand::Rng;
403
404  let mut rng    = rand::rng();
405  let mut stream = Vec::<u8>::new();
406  let mut data   = Vec::<u64>::new();
407  for _ in 0..100 {
408    let test_data  = rng.random::<u64>();
409    for k in test_data.to_le_bytes() {
410      stream.push(k);
411    }
412    data.push(test_data);
413  }
414  let mut pos = 0usize;
415  for k in data {
416    assert_eq!(parse_u64(&stream, &mut pos), k);
417  }
418}
419
420#[cfg(feature = "random")]
421#[test]
422fn test_parse_f32() {
423  #[cfg(feature="random")]
424  use rand::Rng;
425
426  let mut rng    = rand::rng();
427  let mut stream = Vec::<u8>::new();
428  let mut data   = Vec::<f32>::new();
429  for _ in 0..100 {
430    let test_data  = rng.random::<f32>();
431    for k in test_data.to_le_bytes() {
432      stream.push(k);
433    }
434    data.push(test_data);
435  }
436  let mut pos = 0usize;
437  for k in data {
438    assert_eq!(parse_f32(&stream, &mut pos), k);
439  }
440}
441
442#[cfg(feature = "random")]
443#[test]
444fn test_parse_f64() {
445  #[cfg(feature="random")]
446  use rand::Rng;
447
448  let mut rng    = rand::rng();
449  let mut stream = Vec::<u8>::new();
450  let mut data   = Vec::<f64>::new();
451  for _ in 0..100 {
452    let test_data  = rng.random::<f64>();
453    for k in test_data.to_le_bytes() {
454      stream.push(k);
455    }
456    data.push(test_data);
457  }
458  let mut pos = 0usize;
459  for k in data {
460    assert_eq!(parse_f64(&stream, &mut pos), k);
461  }
462}
463
464//--------------------------------------------
465
466#[test]
467fn prop_u8_u16_back_and_forth() {
468  use quickcheck::quickcheck;
469  quickcheck! {
470    fn prop_roundtrip(vec: Vec<u8>) -> bool {
471      let converted = u8_to_u16(&vec);
472      let roundtrip = u16_to_u8(&converted);
473
474      // Only the portion that forms full pairs
475      let expected: Vec<u8> = vec.chunks_exact(2)
476          .flat_map(|chunk| chunk.to_vec())
477          .collect();
478
479      roundtrip == expected
480    }
481  }
482}
483
484
485