iso14229_1/response/
session_ctrl.rs1use std::collections::HashSet;
5use lazy_static::lazy_static;
6use crate::{Configuration, constant::{P2_MAX, P2_STAR_MAX, P2_STAR_MAX_MS}, error::Error, response::Code, ResponseData, SessionType, utils};
7
8lazy_static!(
9 pub static ref SESSION_CTRL_NEGATIVES: HashSet<Code> = HashSet::from([
10 Code::SubFunctionNotSupported,
11 Code::IncorrectMessageLengthOrInvalidFormat,
12 Code::ConditionsNotCorrect,
13 ]);
14);
15
16#[derive(Debug, Default, Clone, Eq, PartialEq)]
17pub struct SessionTiming {
18 pub(crate) p2: u16,
19 pub(crate) p2_star: u16,
20}
21
22impl SessionTiming {
23 #[inline]
24 pub fn new(
25 p2_ms: u16,
26 p2_star_ms: u32,
27 ) -> Result<Self, Error> {
28 if p2_ms > P2_MAX || p2_star_ms > P2_STAR_MAX_MS {
29 return Err(Error::InvalidData(format!("P2: {} or P2*: {}", p2_ms, p2_star_ms)));
30 }
31 let p2_star = (p2_star_ms / 10) as u16;
32 Ok(Self { p2: p2_ms, p2_star })
33 }
34
35 #[inline]
36 pub fn p2_ms(&self) -> u16 {
37 self.p2
38 }
39
40 #[inline]
41 pub fn p2_star_ms(&self) -> u32 {
42 self.p2_star as u32 * 10
43 }
44}
45
46impl<'a> TryFrom<&'a [u8]> for SessionTiming {
47 type Error = Error;
48 #[allow(unused_mut)]
49 fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
50 let data_len = data.len();
51 utils::data_length_check(data_len, 4, true)?;
52
53 let mut offset = 0;
54
55 let mut p2 = u16::from_be_bytes([data[offset], data[offset + 1]]);
56 offset += 2;
57 let mut p2_star = u16::from_be_bytes([data[offset], data[offset + 1]]);
58
59 #[cfg(not(feature = "session_data_check"))]
60 if p2 > P2_MAX || p2_star > P2_STAR_MAX {
61 log::warn!("UDS - invalid session data P2: {}, P2*: {}", p2, p2_star);
62 if p2 > P2_MAX { p2 = P2_MAX; }
63 if p2_star > P2_STAR_MAX { p2_star = P2_STAR_MAX; }
64 }
65 #[cfg(feature = "session_data_check")]
66 if p2 > P2_MAX || p2_star > P2_STAR_MAX {
67 return Err(Error::InvalidSessionData(format!("P2: {}, P2*: {}", p2, p2_star)));
68 }
69
70 Ok(Self { p2, p2_star })
71 }
72}
73
74impl Into<Vec<u8>> for SessionTiming {
75 fn into(self) -> Vec<u8> {
76 let mut result = self.p2.to_be_bytes().to_vec();
77 result.extend(self.p2_star.to_be_bytes());
78 result
79 }
80}
81
82impl ResponseData for SessionTiming {
83 type SubFunc = SessionType;
84 #[inline]
85 fn try_parse(data: &[u8], _: Option<Self::SubFunc>, _: &Configuration) -> Result<Self, Error> {
86 Self::try_from(data)
87 }
88 #[inline]
89 fn to_vec(self, _: &Configuration) -> Vec<u8> {
90 self.into()
91 }
92}