1mod core;
7mod decode;
8
9use crate::header::Header;
10#[cfg(not(feature = "std"))]
11use alloc::vec::Vec;
12
13#[derive(Default)]
15pub struct Record {
16 pub header: Header,
18 pub data: Vec<u8>,
20 pub context: Context,
22}
23
24#[derive(Clone, Default)]
26pub struct Context {
27 pub parent_header: Option<Header>,
29}
30
31impl Record {
32 pub fn payload(&self) -> &[u8] {
33 let begin = self.header.header_size();
34
35 let end = self
37 .data
38 .len()
39 .saturating_sub(if self.header.version.cldic { 4 } else { 0 });
40
41 self.data.get(begin..end).unwrap_or_default()
42 }
43
44 pub fn checksum(&self) -> Option<bool> {
45 if !self.header.version.cldic {
46 return None;
47 }
48
49 let checksum = self
50 .data
51 .chunks(4)
52 .map(|dword_slice| u32::from_le_bytes(dword_slice.try_into().unwrap_or([0; 4])))
53 .fold(0, |acc: u32, dword| acc.wrapping_add(dword));
54
55 Some(checksum == 0)
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use crate::header::Version;
63
64 #[test]
65 fn payload() {
66 let record = Record {
67 data: (0..16).collect(),
68 ..Default::default()
69 };
70 assert_eq!(record.payload(), &[8, 9, 10, 11, 12, 13, 14, 15]);
71
72 let record_with_cldic = Record {
73 header: Header {
74 version: Version {
75 cldic: true,
76 ..Default::default()
77 },
78 ..Default::default()
79 },
80 data: (0..16).collect(),
81 ..Default::default()
82 };
83 assert_eq!(record_with_cldic.payload(), &[8, 9, 10, 11]);
84 }
85
86 #[test]
87 fn payload_with_invalid_header() {
88 let record = Record::default();
89 assert!(record.payload().is_empty());
90
91 let record_with_cldic = Record {
92 header: Header {
93 version: Version {
94 cldic: true,
95 ..Default::default()
96 },
97 ..Default::default()
98 },
99 ..Default::default()
100 };
101 assert!(record_with_cldic.payload().is_empty());
102 }
103}