1use crate::{
2 error::DoipValidationError,
3 header::{PayloadType, ProtocolVersion},
4};
5use ace_proto::{
6 common::{RawFrame, RawFrameMut},
7 doip::constants::{
8 DOIP_HEADER_LEN, DOIP_INV_VERSION_OFFSET, DOIP_LENGTH_OFFSET, DOIP_TYPE_OFFSET,
9 DOIP_VERSION_OFFSET,
10 },
11 DoipFrame, DoipFrameMut,
12};
13
14pub trait DoipFrameExt {
17 fn as_bytes(&self) -> &[u8];
18
19 fn protocol_version(&self) -> Option<u8> {
22 self.as_bytes().get(DOIP_VERSION_OFFSET).copied()
23 }
24
25 fn inverse_protocol_version(&self) -> Option<u8> {
26 self.as_bytes().get(DOIP_INV_VERSION_OFFSET).copied()
27 }
28
29 fn payload_type_raw(&self) -> Option<u16> {
30 let b = self.as_bytes();
31 if b.len() < DOIP_TYPE_OFFSET {
32 return None;
33 }
34 Some(u16::from_be_bytes([
35 b[DOIP_TYPE_OFFSET],
36 b[DOIP_TYPE_OFFSET + 1],
37 ]))
38 }
39
40 fn payload_length_declared(&self) -> Option<u32> {
41 let b = self.as_bytes();
42 if b.len() < DOIP_HEADER_LEN {
43 return None;
44 }
45 Some(u32::from_be_bytes([
46 b[DOIP_LENGTH_OFFSET],
47 b[DOIP_LENGTH_OFFSET + 1],
48 b[DOIP_LENGTH_OFFSET + 2],
49 b[DOIP_LENGTH_OFFSET + 3],
50 ]))
51 }
52
53 fn payload_bytes(&self) -> Option<&[u8]> {
54 let b = self.as_bytes();
55 if b.len() < DOIP_HEADER_LEN {
56 return None;
57 }
58 Some(&b[DOIP_HEADER_LEN..])
59 }
60
61 fn validate_header(&self) -> Result<(), DoipValidationError> {
68 let b = self.as_bytes();
69
70 if b.len() < DOIP_HEADER_LEN {
72 return Err(DoipValidationError::FrameTooShort { actual: b.len() });
73 }
74
75 let version = ProtocolVersion::try_from(b[DOIP_VERSION_OFFSET])
77 .map_err(|_| DoipValidationError::UnsupportedProtocolVersion(b[DOIP_VERSION_OFFSET]))?;
78
79 let inverse = b[DOIP_INV_VERSION_OFFSET];
81 if inverse != !(version as u8) {
82 return Err(DoipValidationError::InvalidInverseProtocolVersion { version, inverse });
83 }
84
85 let payload_type_raw = u16::from_be_bytes([b[DOIP_TYPE_OFFSET], b[DOIP_TYPE_OFFSET + 1]]);
87 PayloadType::try_from(payload_type_raw)
88 .map_err(|_| DoipValidationError::UnknownPayloadType(payload_type_raw))?;
89
90 let declared = u32::from_be_bytes([
92 b[DOIP_LENGTH_OFFSET],
93 b[DOIP_LENGTH_OFFSET + 1],
94 b[DOIP_LENGTH_OFFSET + 2],
95 b[DOIP_LENGTH_OFFSET + 3],
96 ]) as usize;
97 let actual = b.len() - DOIP_HEADER_LEN;
98
99 if declared != actual {
100 return Err(DoipValidationError::PayloadLengthMismatch {
101 declared: declared as u32,
102 actual,
103 });
104 }
105
106 Ok(())
107 }
108
109 fn is_valid(&self) -> bool {
111 self.validate_header().is_ok()
112 }
113
114 fn payload_type(&self) -> Option<Result<PayloadType, DoipValidationError>> {
119 self.payload_type_raw().map(|raw| {
120 PayloadType::try_from(raw).map_err(|_| DoipValidationError::UnknownPayloadType(raw))
121 })
122 }
123 }
125
126impl<'a> DoipFrameExt for DoipFrame<'a> {
129 fn as_bytes(&self) -> &[u8] {
130 RawFrame::as_bytes(self)
131 }
132}
133
134impl<'a> DoipFrameExt for DoipFrameMut<'a> {
135 fn as_bytes(&self) -> &[u8] {
136 RawFrame::as_bytes(self)
137 }
138}
139
140impl<'a> DoipFrameMutExt for DoipFrameMut<'a> {
141 fn as_bytes_mut(&mut self) -> &mut [u8] {
142 RawFrameMut::as_bytes_mut(self)
143 }
144}
145
146pub trait DoipFrameMutExt: DoipFrameExt {
149 fn as_bytes_mut(&mut self) -> &mut [u8];
150
151 fn set_protocol_version(&mut self, version: ProtocolVersion) {
152 let v = version as u8;
153
154 if let Some(b) = self.as_bytes_mut().get_mut(DOIP_VERSION_OFFSET) {
155 *b = v;
156 }
157
158 if let Some(b) = self.as_bytes_mut().get_mut(DOIP_INV_VERSION_OFFSET) {
159 *b = !v;
160 }
161 }
162
163 fn set_payload_type(&mut self, payload_type: PayloadType) {
164 let raw = payload_type as u16;
165 let bytes = raw.to_be_bytes();
166
167 if let Some(b) = self.as_bytes_mut().get_mut(DOIP_TYPE_OFFSET) {
168 *b = bytes[0];
169 }
170
171 if let Some(b) = self.as_bytes_mut().get_mut(DOIP_TYPE_OFFSET + 1) {
172 *b = bytes[1];
173 }
174 }
175
176 fn set_payload_length(&mut self, length: u32) {
177 let bytes = length.to_be_bytes();
178 for (i, &byte) in bytes.iter().enumerate() {
179 if let Some(b) = self.as_bytes_mut().get_mut(DOIP_LENGTH_OFFSET + i) {
180 *b = byte;
181 }
182 }
183 }
184}
185
186