Skip to main content

ace_doip/
message.rs

1use ace_core::{FrameRead, FrameWrite, Writer};
2use ace_proto::doip::constants::{DOIP_HEADER_LEN, DOIP_TYPE_OFFSET};
3
4use crate::{
5    error::{DoipError, DoipValidationError},
6    header::{DoipHeader, PayloadType},
7    payload::Payload,
8};
9
10#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
11pub struct DoipMessage<'a> {
12    pub header: DoipHeader,
13    pub payload: Payload<'a>,
14}
15
16impl<'a> FrameRead<'a> for DoipMessage<'a> {
17    type Error = DoipError;
18
19    fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
20        // Payload type is at bytes 2-3 of the DoIP header
21        if buf.len() < DOIP_HEADER_LEN {
22            return Err(DoipError::Validation(DoipValidationError::FrameTooShort {
23                actual: buf.len(),
24            }));
25        }
26
27        let payload_type_raw =
28            u16::from_be_bytes([buf[DOIP_TYPE_OFFSET], buf[DOIP_TYPE_OFFSET + 1]]);
29        let payload_type = PayloadType::try_from(payload_type_raw).map_err(|_| {
30            DoipError::Validation(DoipValidationError::UnknownPayloadType(payload_type_raw))
31        })?;
32
33        let header = DoipHeader::decode(buf)?;
34        let payload = Payload::decode(payload_type, buf)?;
35
36        Ok(Self { header, payload })
37    }
38}
39
40impl FrameWrite for DoipMessage<'_> {
41    type Error = DoipError;
42
43    fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
44        self.header.encode(buf)?;
45        self.payload.encode(buf)
46    }
47}