1use crate::profile7::{Profile7, Profile7Config}; use crate::{E2EProfile, E2EResult, E2EStatus};
8
9const BITS_PER_BYTE: u32 = 8;
10
11#[derive(Debug, Clone)]
13pub struct Profile7mCheck {
14 rx_source_id: u32,
15 rx_message_type: u8,
16 rx_message_result: u8,
17}
18
19#[derive(Clone)]
21pub struct Profile7m {
22 base: Profile7,
23 config: Profile7Config,
24 pub message_type: u8,
25 pub message_result: u8,
26 pub source_id: u32,
27}
28
29impl Profile7m {
30 fn write_source_id(&self, data: &mut [u8]) {
31 let offset = (self.config.offset / BITS_PER_BYTE) as usize;
32 data[offset + 20..=offset + 23].copy_from_slice(&self.source_id.to_be_bytes());
33 }
34 fn write_message_type(&self, data: &mut [u8]) {
35 let offset = (self.config.offset / BITS_PER_BYTE) as usize;
36 data[offset + 20] = (data[offset + 20] & 0x3F) | ((self.message_type & 0x03) << 6);
37 }
38 fn write_message_result(&self, data: &mut [u8]) {
39 let offset = (self.config.offset / BITS_PER_BYTE) as usize;
40 data[offset + 20] = (data[offset + 20] & 0xCF) | ((self.message_result & 0x03) << 4);
41 }
42 fn read_source_id(&self, data: &[u8]) -> u32 {
43 let offset = (self.config.offset / BITS_PER_BYTE) as usize;
44 u32::from_be_bytes([
45 data[offset + 20],
46 data[offset + 21],
47 data[offset + 22],
48 data[offset + 23],
49 ]) & 0x0FFFFFFF
50 }
51 fn read_message_type(&self, data: &[u8]) -> u8 {
52 let offset = (self.config.offset / BITS_PER_BYTE) as usize;
53 (data[offset + 20] >> 6) & 0x03
54 }
55 fn read_message_result(&self, data: &[u8]) -> u8 {
56 let offset = (self.config.offset / BITS_PER_BYTE) as usize;
57 (data[offset + 20] >> 4) & 0x03
58 }
59 fn do_checks(&mut self, check_items: Profile7mCheck) -> E2EStatus {
60 if self.source_id != check_items.rx_source_id {
61 return E2EStatus::SourceIdError;
62 }
63 if self.message_result != check_items.rx_message_result {
64 return E2EStatus::MessageResultError;
65 }
66 if self.message_type != check_items.rx_message_type {
67 return E2EStatus::MessageTypeError;
68 }
69 E2EStatus::Ok
70 }
71}
72
73impl E2EProfile for Profile7m {
74 type Config = Profile7Config;
75
76 fn new(config: Self::Config) -> E2EResult<Self> {
77 let base = crate::profile7::Profile7::new(config.clone())?; Ok(Self {
80 base,
81 config,
82 message_type: 0x00,
83 message_result: 0x00,
84 source_id: 0x0a0b0c0d,
85 })
86 }
87
88 fn protect(&mut self, data: &mut [u8]) -> E2EResult<()> {
89 self.write_source_id(data);
91 self.write_message_result(data);
92 self.write_message_type(data);
93 self.base.protect(data)?;
94 Ok(())
95 }
96
97 fn check(&mut self, data: &[u8]) -> E2EResult<E2EStatus> {
98 let mut status = self.base.check(data)?;
99 let check_items = Profile7mCheck {
100 rx_source_id: self.read_source_id(data),
101 rx_message_result: self.read_message_result(data),
102 rx_message_type: self.read_message_type(data),
103 };
104 if (status == E2EStatus::Ok) || (status == E2EStatus::OkSomeLost) {
105 status = self.do_checks(check_items);
106 }
107 Ok(status)
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 #[test]
115 fn test_profile7m_basic_request_example() {
116 let config = Profile7Config {
117 min_data_length: 192,
118 ..Default::default()
119 };
120
121 let mut profile_tx = Profile7m::new(config.clone()).unwrap();
122 let mut profile_rx = Profile7m::new(config).unwrap();
123
124 let mut data = vec![
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 ];
128 profile_tx.source_id = 0x00123456;
129 profile_tx.message_result = 0;
130 profile_tx.message_type = 0;
131 profile_tx.protect(&mut data).unwrap();
132 assert_eq!(data[0], 0xae);
134 assert_eq!(data[1], 0x96);
135 assert_eq!(data[2], 0xa7);
136 assert_eq!(data[3], 0xd0);
137 assert_eq!(data[4], 0xa5);
138 assert_eq!(data[5], 0x01);
139 assert_eq!(data[6], 0x75);
140 assert_eq!(data[7], 0x94);
141 assert_eq!(data[8], 0x00);
143 assert_eq!(data[9], 0x00);
144 assert_eq!(data[10], 0x00);
145 assert_eq!(data[11], 0x1c);
146 assert_eq!(data[12], 0x00);
148 assert_eq!(data[13], 0x00);
149 assert_eq!(data[14], 0x00);
150 assert_eq!(data[15], 0x00);
151 assert_eq!(data[16], 0x0a);
153 assert_eq!(data[17], 0x0b);
154 assert_eq!(data[18], 0x0c);
155 assert_eq!(data[19], 0x0d);
156 assert_eq!(data[20], 0x00);
158 assert_eq!(data[21], 0x12);
159 assert_eq!(data[22], 0x34);
160 assert_eq!(data[23], 0x56);
161 profile_rx.source_id = 0x00123456;
162 profile_rx.message_result = 0;
163 profile_rx.message_type = 0;
164 assert_eq!(profile_rx.check(&data).unwrap(), E2EStatus::Ok);
165 }
166
167 #[test]
168 fn test_profile7m_basic_response_example() {
169 let config = Profile7Config {
170 min_data_length: 192,
171 ..Default::default()
172 };
173
174 let mut profile_tx = Profile7m::new(config.clone()).unwrap();
175 let mut profile_rx = Profile7m::new(config).unwrap();
176
177 let mut data = vec![
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 ];
181 profile_tx.source_id = 0x00123456;
182 profile_tx.message_result = 0;
183 profile_tx.message_type = 1;
184 profile_tx.protect(&mut data).unwrap();
185 assert_eq!(data[0], 0xa6);
187 assert_eq!(data[1], 0x2d);
188 assert_eq!(data[2], 0x64);
189 assert_eq!(data[3], 0x86);
190 assert_eq!(data[4], 0xe8);
191 assert_eq!(data[5], 0x3f);
192 assert_eq!(data[6], 0x2c);
193 assert_eq!(data[7], 0xaf);
194 assert_eq!(data[8], 0x00);
196 assert_eq!(data[9], 0x00);
197 assert_eq!(data[10], 0x00);
198 assert_eq!(data[11], 0x1c);
199 assert_eq!(data[12], 0x00);
201 assert_eq!(data[13], 0x00);
202 assert_eq!(data[14], 0x00);
203 assert_eq!(data[15], 0x00);
204 assert_eq!(data[16], 0x0a);
206 assert_eq!(data[17], 0x0b);
207 assert_eq!(data[18], 0x0c);
208 assert_eq!(data[19], 0x0d);
209 assert_eq!(data[20], 0x40);
211 assert_eq!(data[21], 0x12);
212 assert_eq!(data[22], 0x34);
213 assert_eq!(data[23], 0x56);
214 profile_rx.source_id = 0x00123456;
215 profile_rx.message_result = 0;
216 profile_rx.message_type = 1;
217 assert_eq!(profile_rx.check(&data).unwrap(), E2EStatus::Ok);
218 }
219
220 #[test]
221 fn test_profile7m_basic_error_example() {
222 let config = Profile7Config {
223 min_data_length: 192,
224 ..Default::default()
225 };
226
227 let mut profile_tx = Profile7m::new(config.clone()).unwrap();
228 let mut profile_rx = Profile7m::new(config).unwrap();
229
230 let mut data = vec![
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 ];
234 profile_tx.source_id = 0x00123456;
235 profile_tx.message_result = 1;
236 profile_tx.message_type = 1;
237 profile_tx.protect(&mut data).unwrap();
238 assert_eq!(data[0], 0x09);
240 assert_eq!(data[1], 0xd9);
241 assert_eq!(data[2], 0xe8);
242 assert_eq!(data[3], 0x0c);
243 assert_eq!(data[4], 0x47);
244 assert_eq!(data[5], 0x34);
245 assert_eq!(data[6], 0x32);
246 assert_eq!(data[7], 0x02);
247 assert_eq!(data[8], 0x00);
249 assert_eq!(data[9], 0x00);
250 assert_eq!(data[10], 0x00);
251 assert_eq!(data[11], 0x1c);
252 assert_eq!(data[12], 0x00);
254 assert_eq!(data[13], 0x00);
255 assert_eq!(data[14], 0x00);
256 assert_eq!(data[15], 0x00);
257 assert_eq!(data[16], 0x0a);
259 assert_eq!(data[17], 0x0b);
260 assert_eq!(data[18], 0x0c);
261 assert_eq!(data[19], 0x0d);
262 assert_eq!(data[20], 0x50);
264 assert_eq!(data[21], 0x12);
265 assert_eq!(data[22], 0x34);
266 assert_eq!(data[23], 0x56);
267 profile_rx.source_id = 0x00123456;
268 profile_rx.message_result = 1;
269 profile_rx.message_type = 1;
270 assert_eq!(profile_rx.check(&data).unwrap(), E2EStatus::Ok);
271 }
272}