use ace_core::codec::FrameRead;
use ace_proto::common::{RawFrame, RawFrameMut};
use ace_proto::uds::{UdsFrame, UdsFrameMut};
use crate::constants::{
MIN_FRAME_LEN, MIN_SUB_FUNCTION_FRAME_LEN, NEGATIVE_RESPONSE_NRC_OFFSET,
NEGATIVE_RESPONSE_REQUESTED_SID_OFFSET, SUB_FUNCTION_OFFSET, SUB_FUNCTION_VALUE_MASK,
SUPPRESS_POSITIVE_RESPONSE_MASK,
};
use crate::error::{UdsError, ValidationError};
use crate::message::ServiceIdentifier;
use crate::message::UdsMessage;
use crate::message::{decode_message, NegativeResponseCode};
pub trait UdsFrameExt<'a> {
#[must_use]
fn service_identifier(&self) -> Option<ServiceIdentifier>;
#[must_use]
fn payload(&self) -> &[u8];
fn data_iter(&self) -> core::slice::Iter<'_, u8>;
#[must_use]
fn sub_function(&self) -> Option<u8>;
#[must_use]
fn sub_function_value(&self) -> Option<u8> {
self.sub_function().map(|sf| sf & SUB_FUNCTION_VALUE_MASK)
}
#[must_use]
fn is_suppressed(&self) -> bool;
#[must_use]
fn is_positive_response(&self) -> bool {
!self.is_negative_response()
}
#[must_use]
fn is_negative_response(&self) -> bool;
#[must_use]
fn negative_response_code(&self) -> Option<NegativeResponseCode>;
#[must_use]
fn requested_service_identifier(&self) -> Option<ServiceIdentifier>;
fn validate(&self) -> Result<(), UdsError>;
#[must_use]
#[inline]
fn is_valid(&self) -> bool {
self.validate().is_ok()
}
fn to_message(&'a self) -> Result<UdsMessage<'a>, UdsError>;
}
pub trait UdsFrameMutExt<'a>: UdsFrameExt<'a> {
fn suppress(&mut self);
fn un_suppress(&mut self);
}
impl<'a> UdsFrameExt<'a> for UdsFrame<'a> {
fn service_identifier(&self) -> Option<ServiceIdentifier> {
let byte = self.as_bytes().first()?;
let mut buf = core::slice::from_ref(byte);
ServiceIdentifier::decode(&mut buf).ok()
}
fn payload(&self) -> &[u8] {
match self.service_identifier() {
Some(_) => &self.as_bytes()[MIN_FRAME_LEN..],
None => self.as_bytes(),
}
}
fn data_iter(&self) -> core::slice::Iter<'_, u8> {
self.payload().iter()
}
fn sub_function(&self) -> Option<u8> {
let sid = self.service_identifier()?;
if !sid.has_sub_function() {
return None;
}
self.as_bytes().get(SUB_FUNCTION_OFFSET).copied()
}
fn is_suppressed(&self) -> bool {
match self.sub_function() {
Some(sf) => sf & SUPPRESS_POSITIVE_RESPONSE_MASK != 0,
None => false,
}
}
fn is_negative_response(&self) -> bool {
self.service_identifier() == Some(ServiceIdentifier::NegativeResponse)
}
fn negative_response_code(&self) -> Option<NegativeResponseCode> {
if !self.is_negative_response() {
return None;
}
let byte = self.as_bytes().get(NEGATIVE_RESPONSE_NRC_OFFSET)?;
let mut buf = core::slice::from_ref(byte);
NegativeResponseCode::decode(&mut buf).ok()
}
fn requested_service_identifier(&self) -> Option<ServiceIdentifier> {
if !self.is_negative_response() {
return None;
}
let byte = self
.as_bytes()
.get(NEGATIVE_RESPONSE_REQUESTED_SID_OFFSET)?;
let mut buf = core::slice::from_ref(byte);
ServiceIdentifier::decode(&mut buf).ok()
}
fn validate(&self) -> Result<(), UdsError> {
if self.as_bytes().is_empty() {
return Err(ValidationError::InvalidLength {
expected: MIN_FRAME_LEN,
actual: 0,
}
.into());
}
let sid = self
.service_identifier()
.ok_or_else(|| ValidationError::UnsupportedService(self.as_bytes()[0]))?;
if sid.has_sub_function() && self.as_bytes().len() < MIN_SUB_FUNCTION_FRAME_LEN {
return Err(ValidationError::InvalidLength {
expected: MIN_SUB_FUNCTION_FRAME_LEN,
actual: self.as_bytes().len(),
}
.into());
}
Ok(())
}
fn to_message(&'a self) -> Result<UdsMessage<'a>, UdsError> {
decode_message(self.as_bytes())
}
}
impl<'a> UdsFrameExt<'a> for UdsFrameMut<'a> {
fn service_identifier(&self) -> Option<ServiceIdentifier> {
UdsFrame::from_slice(self.as_bytes()).service_identifier()
}
fn payload(&self) -> &[u8] {
match self.service_identifier() {
Some(_) => &self.as_bytes()[MIN_FRAME_LEN..],
None => self.as_bytes(),
}
}
fn data_iter(&self) -> core::slice::Iter<'_, u8> {
self.payload().iter()
}
fn sub_function(&self) -> Option<u8> {
UdsFrame::from_slice(self.as_bytes()).sub_function()
}
fn is_suppressed(&self) -> bool {
UdsFrame::from_slice(self.as_bytes()).is_suppressed()
}
fn is_negative_response(&self) -> bool {
UdsFrame::from_slice(self.as_bytes()).is_negative_response()
}
fn negative_response_code(&self) -> Option<NegativeResponseCode> {
UdsFrame::from_slice(self.as_bytes()).negative_response_code()
}
fn requested_service_identifier(&self) -> Option<ServiceIdentifier> {
UdsFrame::from_slice(self.as_bytes()).requested_service_identifier()
}
fn validate(&self) -> Result<(), UdsError> {
UdsFrame::from_slice(self.as_bytes()).validate()
}
fn to_message(&'a self) -> Result<UdsMessage<'a>, UdsError> {
decode_message(self.as_bytes())
}
}
impl<'a> UdsFrameMutExt<'a> for UdsFrameMut<'a> {
fn suppress(&mut self) {
if self.is_suppressed() || self.sub_function().is_none() {
return;
}
if let Some(sf) = self.as_bytes_mut().get_mut(SUB_FUNCTION_OFFSET) {
*sf |= SUPPRESS_POSITIVE_RESPONSE_MASK;
}
}
fn un_suppress(&mut self) {
if !self.is_suppressed() || self.sub_function().is_none() {
return;
}
if let Some(sf) = self.as_bytes_mut().get_mut(SUB_FUNCTION_OFFSET) {
*sf &= SUB_FUNCTION_VALUE_MASK;
}
}
}