use crate::{
DiagnosticSessionType, Error, NegativeResponseCode, SingleValueWireFormat,
SuppressablePositiveResponse, WireFormat,
};
use byteorder::{ReadBytesExt, WriteBytesExt};
const DIAGNOSTIC_SESSION_CONTROL_NEGATIVE_RESPONSE_CODES: [NegativeResponseCode; 3] = [
NegativeResponseCode::SubFunctionNotSupported,
NegativeResponseCode::IncorrectMessageLengthOrInvalidFormat,
NegativeResponseCode::ConditionsNotCorrect,
];
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DiagnosticSessionControlRequest {
session_type: SuppressablePositiveResponse<DiagnosticSessionType>,
}
impl DiagnosticSessionControlRequest {
pub(crate) fn new(
suppress_positive_response: bool,
session_type: DiagnosticSessionType,
) -> Self {
Self {
session_type: SuppressablePositiveResponse::new(
suppress_positive_response,
session_type,
),
}
}
#[must_use]
pub fn suppress_positive_response(&self) -> bool {
self.session_type.suppress_positive_response()
}
#[must_use]
pub fn session_type(&self) -> DiagnosticSessionType {
self.session_type.value()
}
#[must_use]
pub fn allowed_nack_codes() -> &'static [NegativeResponseCode] {
&DIAGNOSTIC_SESSION_CONTROL_NEGATIVE_RESPONSE_CODES
}
}
impl WireFormat for DiagnosticSessionControlRequest {
fn decode<T: std::io::Read>(reader: &mut T) -> Result<Option<Self>, Error> {
let session_type = SuppressablePositiveResponse::try_from(reader.read_u8()?)?;
Ok(Some(Self { session_type }))
}
fn required_size(&self) -> usize {
1
}
fn encode<T: std::io::Write>(&self, writer: &mut T) -> Result<usize, Error> {
writer.write_u8(u8::from(self.session_type))?;
Ok(1)
}
fn is_positive_response_suppressed(&self) -> bool {
self.suppress_positive_response()
}
}
impl SingleValueWireFormat for DiagnosticSessionControlRequest {}
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct DiagnosticSessionControlResponse {
pub session_type: DiagnosticSessionType,
pub p2_server_max: u16,
pub p2_star_server_max: u16,
}
impl DiagnosticSessionControlResponse {
pub(crate) fn new(
session_type: DiagnosticSessionType,
p2_server_max: u16,
p2_star_server_max: u16,
) -> Self {
Self {
session_type,
p2_server_max,
p2_star_server_max,
}
}
}
impl WireFormat for DiagnosticSessionControlResponse {
fn decode<T: std::io::Read>(reader: &mut T) -> Result<Option<Self>, Error> {
let session_type = DiagnosticSessionType::try_from(reader.read_u8()?)?;
let p2_server_max = reader.read_u16::<byteorder::BigEndian>()?;
let p2_star_server_max = reader.read_u16::<byteorder::BigEndian>()?;
Ok(Some(Self {
session_type,
p2_server_max,
p2_star_server_max,
}))
}
fn required_size(&self) -> usize {
5
}
fn encode<T: std::io::Write>(&self, buffer: &mut T) -> Result<usize, Error> {
buffer.write_u8(u8::from(self.session_type))?;
buffer.write_u16::<byteorder::BigEndian>(self.p2_server_max)?;
buffer.write_u16::<byteorder::BigEndian>(self.p2_star_server_max)?;
Ok(5)
}
}
impl SingleValueWireFormat for DiagnosticSessionControlResponse {}
#[cfg(test)]
mod request {
use super::*;
use crate::DiagnosticSessionType;
#[test]
fn test_diagnostic_session_control_request() {
let bytes: [u8; 1] = [0x02];
let req: DiagnosticSessionControlRequest =
DiagnosticSessionControlRequest::decode_single_value(&mut bytes.as_slice()).unwrap();
assert!(!req.suppress_positive_response());
assert_eq!(
req.session_type(),
DiagnosticSessionType::ProgrammingSession
);
let mut buffer = Vec::new();
req.encode(&mut buffer).unwrap();
assert_eq!(buffer, bytes);
assert_eq!(req.required_size(), 1);
}
}
#[cfg(test)]
mod response {
use super::*;
use crate::DiagnosticSessionType;
#[test]
fn test_diagnostic_session_control_response() {
let bytes = [0x02, 0x11, 0x22, 0x33, 0x44];
let resp: DiagnosticSessionControlResponse =
DiagnosticSessionControlResponse::decode_single_value(&mut bytes.as_slice()).unwrap();
assert_eq!(resp.session_type, DiagnosticSessionType::ProgrammingSession);
assert_eq!(resp.p2_server_max, 0x1122);
assert_eq!(resp.p2_star_server_max, 0x3344);
let mut buffer = Vec::new();
resp.encode(&mut buffer).unwrap();
assert_eq!(buffer, bytes);
assert_eq!(resp.required_size(), 5);
}
}