1use crate::profile4::{Profile4, Profile4Config}; use crate::{E2EProfile, E2EResult, E2EStatus};
8
9const BITS_PER_BYTE: u16 = 8;
10
11#[derive(Debug, Clone)]
13pub struct Profile4mCheck {
14 rx_source_id: u32,
15 rx_message_type: u8,
16 rx_message_result: u8,
17}
18
19#[derive(Clone)]
21pub struct Profile4m {
22 base: Profile4,
23 config: Profile4Config,
24 pub message_type: u8,
25 pub message_result: u8,
26 pub source_id: u32,
27}
28
29impl Profile4m {
30 fn write_source_id(&self, data: &mut [u8]) {
31 let offset = (self.config.offset / BITS_PER_BYTE) as usize;
32 data[offset + 12..=offset + 15].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 + 12] = (data[offset + 12] & 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 + 12] = (data[offset + 12] & 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 + 12],
46 data[offset + 13],
47 data[offset + 14],
48 data[offset + 15],
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 + 12] >> 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 + 12] >> 4) & 0x03
58 }
59 fn do_checks(&mut self, check_items: Profile4mCheck) -> 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 Profile4m {
74 type Config = Profile4Config;
75
76 fn new(config: Self::Config) -> E2EResult<Self> {
77 let base = crate::profile4::Profile4::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 = Profile4mCheck {
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_profile4m_basic_request_example() {
116 let mut profile_tx = Profile4m::new(Profile4Config::default()).unwrap();
117 let mut profile_rx = Profile4m::new(Profile4Config::default()).unwrap();
118
119 let mut data = vec![
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 ];
123 profile_tx.source_id = 0x00123456;
124 profile_tx.message_result = 0;
125 profile_tx.message_type = 0;
126 profile_tx.protect(&mut data).unwrap();
127 assert_eq!(data[0], 0x00);
129 assert_eq!(data[1], 0x14);
130 assert_eq!(data[2], 0x00);
132 assert_eq!(data[3], 0x00);
133 assert_eq!(data[4], 0x0a);
135 assert_eq!(data[5], 0x0b);
136 assert_eq!(data[6], 0x0c);
137 assert_eq!(data[7], 0x0d);
138 assert_eq!(data[8], 0xae);
140 assert_eq!(data[9], 0x67);
141 assert_eq!(data[10], 0x4c);
142 assert_eq!(data[11], 0xa0);
143 assert_eq!(data[12], 0x00);
145 assert_eq!(data[13], 0x12);
146 assert_eq!(data[14], 0x34);
147 assert_eq!(data[15], 0x56);
148 profile_rx.source_id = 0x00123456;
149 profile_rx.message_result = 0;
150 profile_rx.message_type = 0;
151 assert_eq!(profile_rx.check(&data).unwrap(), E2EStatus::Ok);
152 }
153 #[test]
154 fn test_profile4m_basic_response_example() {
155 let mut profile_tx = Profile4m::new(Profile4Config::default()).unwrap();
156 let mut profile_rx = Profile4m::new(Profile4Config::default()).unwrap();
157
158 let mut data = vec![
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 ];
162 profile_tx.source_id = 0x00123456;
163 profile_tx.message_result = 0;
164 profile_tx.message_type = 1;
165 profile_tx.protect(&mut data).unwrap();
166 assert_eq!(data[0], 0x00);
168 assert_eq!(data[1], 0x14);
169 assert_eq!(data[2], 0x00);
171 assert_eq!(data[3], 0x00);
172 assert_eq!(data[4], 0x0a);
174 assert_eq!(data[5], 0x0b);
175 assert_eq!(data[6], 0x0c);
176 assert_eq!(data[7], 0x0d);
177 assert_eq!(data[8], 0x85);
179 assert_eq!(data[9], 0x25);
180 assert_eq!(data[10], 0x76);
181 assert_eq!(data[11], 0x19);
182 assert_eq!(data[12], 0x40);
184 assert_eq!(data[13], 0x12);
185 assert_eq!(data[14], 0x34);
186 assert_eq!(data[15], 0x56);
187 profile_rx.source_id = 0x00123456;
188 profile_rx.message_result = 0;
189 profile_rx.message_type = 1;
190 assert_eq!(profile_rx.check(&data).unwrap(), E2EStatus::Ok);
191 }
192 #[test]
193 fn test_profile4m_basic_error_example() {
194 let mut profile_tx = Profile4m::new(Profile4Config::default()).unwrap();
195 let mut profile_rx = Profile4m::new(Profile4Config::default()).unwrap();
196
197 let mut data = vec![
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 ];
201 profile_tx.source_id = 0x00123456;
202 profile_tx.message_result = 1;
203 profile_tx.message_type = 1;
204 profile_tx.protect(&mut data).unwrap();
205 assert_eq!(data[0], 0x00);
207 assert_eq!(data[1], 0x14);
208 assert_eq!(data[2], 0x00);
210 assert_eq!(data[3], 0x00);
211 assert_eq!(data[4], 0x0a);
213 assert_eq!(data[5], 0x0b);
214 assert_eq!(data[6], 0x0c);
215 assert_eq!(data[7], 0x0d);
216 assert_eq!(data[8], 0x23);
218 assert_eq!(data[9], 0x45);
219 assert_eq!(data[10], 0x57);
220 assert_eq!(data[11], 0x0f);
221 assert_eq!(data[12], 0x50);
223 assert_eq!(data[13], 0x12);
224 assert_eq!(data[14], 0x34);
225 assert_eq!(data[15], 0x56);
226 profile_rx.source_id = 0x00123456;
227 profile_rx.message_result = 1;
228 profile_rx.message_type = 1;
229 assert_eq!(profile_rx.check(&data).unwrap(), E2EStatus::Ok);
230 }
231}