#![warn(clippy::pedantic)]
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
mod common;
pub use common::*;
mod error;
pub use error::Error;
pub use uds_protocol_derive::Identifier;
mod protocol_definitions;
pub use protocol_definitions::{ProtocolIdentifier, ProtocolPayload};
mod request;
pub use request::Request;
mod response;
pub use response::{Response, UdsResponse};
mod service;
pub use service::UdsServiceType;
mod services;
pub use services::*;
mod traits;
pub use traits::{
DiagnosticDefinition, Identifier, IterableWireFormat, RoutineIdentifier, SingleValueWireFormat,
WireFormat,
};
pub const SUCCESS: u8 = 0x80;
pub const PENDING: u8 = 0x78;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct UdsSpec;
impl DiagnosticDefinition for UdsSpec {
type RID = UDSRoutineIdentifier;
type DID = ProtocolIdentifier;
type RoutinePayload = ProtocolPayload;
type DiagnosticPayload = ProtocolPayload;
}
pub type ProtocolRequest = Request<UdsSpec>;
pub type ProtocolResponse = Response<UdsSpec>;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RoutineControlSubFunction {
StartRoutine,
StopRoutine,
RequestRoutineResults,
}
impl From<RoutineControlSubFunction> for u8 {
fn from(value: RoutineControlSubFunction) -> Self {
match value {
RoutineControlSubFunction::StartRoutine => 0x01,
RoutineControlSubFunction::StopRoutine => 0x02,
RoutineControlSubFunction::RequestRoutineResults => 0x03,
}
}
}
impl From<u8> for RoutineControlSubFunction {
fn from(value: u8) -> Self {
match value {
0x01 => RoutineControlSubFunction::StartRoutine,
0x02 => RoutineControlSubFunction::StopRoutine,
0x03 => RoutineControlSubFunction::RequestRoutineResults,
_ => panic!("Invalid routine control subfunction: {value}"),
}
}
}
impl WireFormat for Vec<u8> {
fn decode<T: std::io::Read>(reader: &mut T) -> Result<Option<Self>, Error> {
let mut data = Vec::new();
reader.read_to_end(&mut data)?;
Ok(Some(data))
}
fn required_size(&self) -> usize {
self.len()
}
fn encode<T: std::io::Write>(&self, writer: &mut T) -> Result<usize, Error> {
writer.write_all(self)?;
Ok(self.len())
}
}
impl SingleValueWireFormat for Vec<u8> {}
impl IterableWireFormat for Vec<u8> {}
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DtcSettings {
On,
Off,
}
impl From<DtcSettings> for u8 {
fn from(value: DtcSettings) -> Self {
match value {
DtcSettings::On => 0x01,
DtcSettings::Off => 0x02,
}
}
}
impl From<u8> for DtcSettings {
fn from(value: u8) -> Self {
match value {
0x01 => Self::On,
0x02 => Self::Off,
_ => panic!("Invalid DTC setting: {value}"),
}
}
}