Skip to main content

ace_uds/message/
mod.rs

1pub mod payload;
2pub mod service;
3pub mod services;
4
5use ace_core::{DiagError, FrameRead, FrameWrite};
6pub use payload::UdsPayload;
7pub use service::ServiceIdentifier;
8pub use services::*;
9
10use crate::{constants::MIN_FRAME_LEN, UdsError, ValidationError};
11
12#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
13pub struct UdsMessage<'a> {
14    pub sid: Option<ServiceIdentifier>,
15    pub payload: UdsPayload<'a>,
16}
17
18// region: UdsMessage codec
19
20impl<'a> FrameRead<'a> for UdsMessage<'a> {
21    type Error = UdsError;
22
23    fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
24        if buf.is_empty() {
25            return Err(ValidationError::InvalidLength {
26                expected: MIN_FRAME_LEN,
27                actual: 0,
28            }
29            .into());
30        }
31
32        // Peek at the first byte - if it matches a known SID consume it and
33        // dispatch to the appropriate payload decoder. If it does not match,
34        // treat the entire buffer as periodic data (no SID consumed).
35        let mut sid_buf = *buf;
36        match ServiceIdentifier::decode(&mut sid_buf) {
37            Ok(sid) => {
38                // Advance the real cursor past the SID byte
39                *buf = sid_buf;
40                let payload = UdsPayload::decode(Some(sid), buf)?;
41                Ok(Self {
42                    sid: Some(sid),
43                    payload,
44                })
45            }
46            Err(_) => {
47                // No SID consumed - entire buffer is periodic data
48                let payload = UdsPayload::decode(None, buf)?;
49                Ok(Self { sid: None, payload })
50            }
51        }
52    }
53}
54
55impl FrameWrite for UdsMessage<'_> {
56    type Error = UdsError;
57
58    fn encode<W: ace_core::codec::Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
59        if let Some(sid) = &self.sid {
60            sid.encode(buf).map_err(|e| {
61                let d: DiagError = e.into();
62                UdsError::from(d)
63            })?;
64        }
65        self.payload.encode(buf)
66    }
67}
68
69// endregion: UdsMessage codec
70
71pub fn decode_message<'a>(bytes: &'a [u8]) -> Result<UdsMessage<'a>, UdsError> {
72    if bytes.is_empty() {
73        return Err(ValidationError::InvalidLength {
74            expected: MIN_FRAME_LEN,
75            actual: 0,
76        }
77        .into());
78    }
79    let mut sid_buf = &bytes[..1];
80    let sid = ServiceIdentifier::decode(&mut sid_buf)
81        .map_err(|_| ValidationError::UnsupportedService(bytes[0]))?;
82    let mut payload_buf = &bytes[MIN_FRAME_LEN..];
83    let payload = UdsPayload::decode(Some(sid), &mut payload_buf)?;
84    Ok(UdsMessage {
85        sid: Some(sid),
86        payload,
87    })
88}