1#![allow(unused_imports)]
2
3mod session_ctrl; pub use session_ctrl::*;
6mod ecu_reset; pub use ecu_reset::*;
8mod security_access; pub use security_access::*;
10mod communication_ctrl; pub use communication_ctrl::*;
12#[cfg(any(feature = "std2020"))]
13mod authentication; #[cfg(any(feature = "std2020"))]
15pub use authentication::*;
16mod tester_present; pub use tester_present::*;
18#[cfg(any(feature = "std2006", feature = "std2013"))]
19mod access_timing_param; #[cfg(any(feature = "std2006", feature = "std2013"))]
21pub use access_timing_param::*;
22mod secured_data_trans; pub use secured_data_trans::*;
24mod ctrl_dtc_setting; pub use ctrl_dtc_setting::*;
26mod response_on_event; pub use response_on_event::*;
28mod link_ctrl; pub use link_ctrl::*;
30
31mod read_did; pub use read_did::*;
34mod read_mem_by_addr; pub use read_mem_by_addr::*;
36mod read_scaling_did; pub use read_scaling_did::*;
38mod read_data_by_pid; pub use read_data_by_pid::*;
40mod dynamically_define_did; pub use dynamically_define_did::*;
42mod write_did; pub use write_did::*;
44mod write_mem_by_addr; pub use write_mem_by_addr::*;
46
47mod clear_diagnostic_info; pub use clear_diagnostic_info::*;
50mod read_dtc_info; pub use read_dtc_info::*;
52
53mod io_ctrl; pub use io_ctrl::*;
56
57mod routine_ctrl; pub use routine_ctrl::*;
60
61mod request_load; pub use request_load::*;
64mod transfer_data; pub use transfer_data::*;
66mod request_transfer_exit; pub use request_transfer_exit::*;
68#[cfg(any(feature = "std2013", feature = "std2020"))]
69mod request_file_transfer; #[cfg(any(feature = "std2013", feature = "std2020"))]
71pub use request_file_transfer::*;
72
73mod code;
74pub use code::Code;
75
76use crate::{Configuration, constant::POSITIVE_OFFSET, Error, ResponseData, Service, utils};
108
109#[derive(Debug, Copy, Clone)]
125pub struct SubFunction<T>(T);
126
127impl<F: Copy> SubFunction<F> {
128 pub fn new(
129 function: F,
130 ) -> Self {
131 Self(function)
132 }
133
134 #[inline]
135 pub fn function(&self) -> F {
136 self.0
137 }
138}
139
140impl<T: Into<u8>> Into<u8> for SubFunction<T> {
141 fn into(self) -> u8 {
142 self.0.into()
143 }
144}
145
146#[derive(Debug, Clone)]
147pub struct Response<F> {
148 service: Service,
149 negative: bool,
150 sub_func: Option<SubFunction<F>>,
151 data: Vec<u8>, }
153
154impl<F: Copy> Response<F> {
155 pub fn new(
156 service: Service,
157 negative: bool,
158 sub_func: Option<SubFunction<F>>,
159 data: Vec<u8>,
160 ) -> Self {
161 Self { service, negative, sub_func, data, }
162 }
163
164 #[inline]
165 pub fn service(&self) -> Service {
166 self.service
167 }
168
169 #[inline]
170 pub fn sub_function(&self) -> Option<SubFunction<F>> {
171 self.sub_func
172 }
173
174 #[inline]
175 pub const fn is_negative(&self) -> bool {
176 self.negative
177 }
178
179 #[inline]
180 pub fn nrc_code(&self) -> Result<Code, Error> {
181 if !self.negative {
182 return Err(Error::OtherError("get NRC from positive".into()));
183 }
184
185 if self.data.len() != 1 {
186 return Err(Error::OtherError("invalid data length when getting NRC from negative".into()));
187 }
188
189 Ok(Code::from(self.data[0]))
190 }
191
192 #[inline]
193 pub fn raw_data(&self) -> &[u8] {
194 self.data.as_slice()
195 }
196
197 #[inline]
198 pub fn data<T: ResponseData<SubFunc = F>>(&self, cfg: &Configuration) -> Result<T, Error> {
199 T::try_parse(self.data.as_slice(), match self.sub_func {
200 Some(v) => Some(v.0),
201 None => None,
202 }, cfg)
203 }
204}
205
206impl<F: Into<u8>> Into<Vec<u8>> for Response<F> {
207 fn into(mut self) -> Vec<u8> {
208 let mut result = if self.negative {
209 vec![Service::NRC.into(), ]
210 }
211 else {
212 vec![]
213 };
214
215 let service: u8 = self.service.into();
216 result.push(service | POSITIVE_OFFSET);
217
218 if let Some(sub_func) = self.sub_func {
219 result.push(sub_func.into());
220 }
221
222 result.append(&mut self.data);
223
224 result
225 }
226}
227
228impl<F: TryFrom<u8, Error = Error> + Copy> TryFrom<Vec<u8>> for Response<F> {
229 type Error = Error;
230 fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> {
231 let data_len = data.len();
232 utils::data_length_check(data_len, 1, false)?;
233
234 let mut offset = 0;
235 let service = data[offset];
236 let service = if service == Service::NRC.into() {
237 Ok(Service::NRC)
238 }
239 else {
240 Service::try_from(service & !POSITIVE_OFFSET)
241 }?;
242 offset += 1;
243 match service {
244 Service::SessionCtrl |
245 Service::ECUReset |
246 Service::SecurityAccess |
247 Service::CommunicationCtrl |
248 Service::ReadDTCInfo |
249 Service::RoutineCtrl |
250 Service::CtrlDTCSetting |
251 Service::TesterPresent |
252 Service::LinkCtrl |
253 Service::DynamicalDefineDID => {
254 utils::data_length_check(data_len, offset + 1, false)?;
255
256 let sub_func = F::try_from(data[offset])?;
257 offset += 1;
258 let data = data[offset..].to_vec();
259
260 Ok(Self::new(service, false, Some(SubFunction::new(sub_func)), data))
261 },
262 Service::ClearDiagnosticInfo |
263 Service::ReadDID |
264 Service::ReadMemByAddr |
265 Service::ReadScalingDID |
266 Service::ReadDataByPeriodId |
267 Service::WriteDID |
268 Service::IOCtrl |
269 Service::RequestDownload |
270 Service::RequestUpload |
271 Service::TransferData |
272 Service::RequestTransferExit |
273 Service::WriteMemByAddr |
274 Service::SecuredDataTrans |
275 Service::ResponseOnEvent => {
276 Ok(Self::new(service, false, None, data[offset..].to_vec()))
277 },
278 #[cfg(any(feature = "std2020"))]
279 Service::Authentication => {
280 utils::data_length_check(data_len, offset + 1, false)?;
281
282 let sub_func = F::try_from(data[offset])?;
283 offset += 1;
284 let data = data[offset..].to_vec();
285
286 Ok(Self::new(service, false, Some(SubFunction::new(sub_func)), data))
287 },
288 #[cfg(any(feature = "std2013", feature = "std2020"))]
289 Service::RequestFileTransfer => {
290 utils::data_length_check(data_len, offset + 1, false)?;
291
292 let sub_func = F::try_from(data[offset])?;
293 offset += 1;
294 let data = data[offset..].to_vec();
295
296 Ok(Self::new(service, false, Some(SubFunction::new(sub_func)), data))
297 },
298 #[cfg(any(feature = "std2006", feature = "std2013"))]
299 Service::AccessTimingParam => {
300 utils::data_length_check(data_len, offset + 1, false)?;
301
302 let sub_func = F::try_from(data[offset])?;
303 offset += 1;
304 let data = data[offset..].to_vec();
305
306 Ok(Self::new(service, false, Some(SubFunction::new(sub_func)), data))
307 },
308 Service::NRC => {
309 utils::data_length_check(data_len, offset + 2, true)?;
310 let nrc_service = Service::try_from(data[offset])?;
311 offset += 1;
312
313 let data = data[offset..].to_vec();
314
315 Ok(Self::new(nrc_service, true, None, data))
316 },
317 }
318 }
319}