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 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}