1use crate::{error::Error, utils, *};
2use getset::{CopyGetters, Getters};
3use std::fmt::{Display, Formatter};
4
5#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
6#[get_copy = "pub"]
7pub struct HeaderNegative {
8 pub(crate) code: HeaderNegativeCode,
9}
10
11impl HeaderNegative {
12 pub fn new(code: HeaderNegativeCode) -> Self {
13 Self { code }
14 }
15
16 #[inline]
17 const fn length() -> usize {
18 1
19 }
20}
21
22impl TryFrom<&[u8]> for HeaderNegative {
23 type Error = Error;
24 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
25 let (_, offset) = utils::data_len_check(data, Self::length(), true)?;
26 let code = data[offset];
27 let code = HeaderNegativeCode::from(code);
28
29 Ok(Self { code })
30 }
31}
32
33impl From<HeaderNegative> for Vec<u8> {
34 fn from(val: HeaderNegative) -> Self {
35 let mut result = HEADER_NEGATIVE.to_be_bytes().to_vec();
36 let length = HeaderNegative::length() as u32;
37 result.extend(length.to_be_bytes());
38 result.push(val.code.into());
39
40 result
41 }
42}
43
44#[derive(Debug, Clone, Eq, PartialEq, Getters, CopyGetters)]
50pub struct VehicleID {
51 #[get = "pub"]
53 pub(crate) vin: String,
54 #[get_copy = "pub"]
55 pub(crate) address: LogicAddress,
56 #[get_copy = "pub"]
57 pub(crate) eid: Eid,
58 #[get_copy = "pub"]
59 pub(crate) gid: Gid,
60 #[get_copy = "pub"]
61 pub(crate) further_act: FurtherAction,
62 #[get_copy = "pub"]
63 pub(crate) sync_status: Option<SyncStatus>,
64}
65
66impl VehicleID {
67 pub fn new(
68 vin: String,
69 address: LogicAddress,
70 eid: Eid,
71 gid: Eid,
72 further_act: FurtherAction,
73 sync_status: Option<SyncStatus>,
74 ) -> Result<Self, Error> {
75 let vin_len = vin.len();
76 if vin_len != LENGTH_OF_VIN {
77 return Err(Error::InvalidParam(format!(
78 "length of vin must equal {}",
79 LENGTH_OF_VIN
80 )));
81 }
82
83 Ok(Self {
84 vin,
85 address,
86 eid,
87 gid,
88 further_act,
89 sync_status,
90 })
91 }
92
93 #[inline]
95 const fn length() -> usize {
96 LENGTH_OF_VIN + SIZE_OF_ADDRESS + Eid::length() + Gid::length() + 1
97 }
98}
99
100impl TryFrom<&[u8]> for VehicleID {
101 type Error = Error;
102 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
103 let (data_len, mut offset) = utils::data_len_check(data, Self::length(), false)?;
104 let vin = match String::from_utf8(data[offset..offset + LENGTH_OF_VIN].to_vec()) {
105 Ok(v) => v,
106 Err(_) => {
107 rsutil::warn!("invalid UTF-8 string: {}", hex::encode(data));
108 "-".repeat(data_len)
109 }
110 };
111 offset += LENGTH_OF_VIN;
112 let address =
113 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
114 offset += SIZE_OF_ADDRESS;
115 let address = LogicAddress::from(address);
116 let eid = Eid::try_from(&data[offset..])?;
117 offset += Eid::length();
118 let gid = Gid::try_from(&data[offset..])?;
119 offset += Gid::length();
120 let further_act = FurtherAction::from(data[offset]);
121 offset += 1;
122 let sync_status = match data_len - offset {
123 0 => Ok(None),
124 1 => Ok(Some(SyncStatus::from(data[offset]))),
125 _ => Err(Error::InvalidLength {
126 actual: data_len,
127 expected: Self::length() + 1,
128 }),
129 }?;
130
131 Ok(Self {
132 vin,
133 address,
134 eid,
135 gid,
136 further_act,
137 sync_status,
138 })
139 }
140}
141
142impl From<VehicleID> for Vec<u8> {
143 fn from(val: VehicleID) -> Self {
144 let mut result = UDP_RESP_VEHICLE_IDENTIFIER.to_be_bytes().to_vec();
145 let mut length = VehicleID::length() as u32;
146 if val.sync_status.is_some() {
147 length += 1;
148 }
149 result.extend(length.to_be_bytes());
150 result.extend(val.vin.as_bytes());
151 let address: u16 = val.address.into();
152 result.extend(address.to_be_bytes());
153 result.append(&mut val.eid.into());
154 result.append(&mut val.gid.into());
155 result.push(val.further_act.into());
156 if let Some(status) = val.sync_status {
157 result.push(status.into());
158 }
159
160 result
161 }
162}
163
164#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
165#[get_copy = "pub"]
166pub struct EntityStatus {
167 pub(crate) node_type: NodeType,
169 pub(crate) mcts: u8, pub(crate) ncts: u8, pub(crate) max_data_size: Option<u32>,
175}
176
177impl EntityStatus {
178 pub fn new(node_type: NodeType, mcts: u8, ncts: u8, max_data_size: Option<u32>) -> Self {
179 Self {
180 node_type,
181 mcts,
182 ncts,
183 max_data_size,
184 }
185 }
186
187 #[inline]
189 const fn length() -> usize {
190 1 + 1 + 1
191 }
192}
193
194impl TryFrom<&[u8]> for EntityStatus {
195 type Error = Error;
196 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
197 let (data_len, mut offset) = utils::data_len_check(data, Self::length(), false)?;
198 let node_type = data[offset];
199 offset += 1;
200 let node_type = NodeType::from(node_type);
201 let mcts = data[offset];
202 offset += 1;
203 let ncts = data[offset];
204 offset += 1;
205 let max_data_size = match data_len - offset {
206 0 => Ok(None),
207 4 => Ok(Some(u32::from_be_bytes(
208 data[offset..offset + 4].try_into().unwrap(),
209 ))),
210 _ => Err(Error::InvalidLength {
211 actual: data_len,
212 expected: Self::length() + 4,
213 }),
214 }?;
215
216 Ok(Self {
217 node_type,
218 mcts,
219 ncts,
220 max_data_size,
221 })
222 }
223}
224
225impl From<EntityStatus> for Vec<u8> {
226 fn from(val: EntityStatus) -> Self {
227 let mut result = UDP_RESP_ENTITY_STATUS.to_be_bytes().to_vec();
228 let mut length = EntityStatus::length() as u32;
229 if val.max_data_size.is_some() {
230 length += 4;
231 }
232 result.extend(length.to_be_bytes());
233 result.push(val.node_type.into());
234 result.push(val.mcts);
235 result.push(val.ncts);
236 if let Some(size) = val.max_data_size {
237 result.extend(size.to_be_bytes());
238 }
239
240 result
241 }
242}
243
244impl Display for EntityStatus {
245 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246 f.debug_struct("DoIP Entity Status")
247 .field("\n Node Type", &self.node_type)
248 .field("\n Max. TCP Connectors", &self.mcts)
249 .field("\n Current TCP Connectors", &self.ncts)
250 .field("\n Max. Data Length", &self.max_data_size)
251 .finish()
252 }
253}
254
255#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
256#[get_copy = "pub"]
257pub struct DiagnosticPowerMode {
258 pub(crate) mode: PowerMode,
260}
261
262impl DiagnosticPowerMode {
263 pub fn new(mode: PowerMode) -> Self {
264 Self { mode }
265 }
266
267 #[inline]
268 const fn length() -> usize {
269 1
270 }
271}
272
273impl TryFrom<&[u8]> for DiagnosticPowerMode {
274 type Error = Error;
275 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
276 let (_, offset) = utils::data_len_check(data, Self::length(), true)?;
277 let mode = data[offset];
278 let mode = PowerMode::from(mode);
279 Ok(Self { mode })
280 }
281}
282
283impl From<DiagnosticPowerMode> for Vec<u8> {
284 fn from(val: DiagnosticPowerMode) -> Self {
285 let mut result = UDP_RESP_DIAGNOSTIC_POWER_MODE.to_be_bytes().to_vec();
286 let length = DiagnosticPowerMode::length() as u32;
287 result.extend(length.to_be_bytes());
288 result.push(val.mode.into());
289 result
290 }
291}
292#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
296#[get_copy = "pub"]
297pub struct RoutingActive {
298 pub(crate) dst_addr: LogicAddress,
300 pub(crate) src_addr: LogicAddress,
301 pub(crate) active_code: ActiveCode,
302 pub(crate) reserved: u32,
303 pub(crate) user_def: Option<u32>,
305}
306
307impl RoutingActive {
308 pub fn new(
309 dst_addr: LogicAddress,
310 src_addr: LogicAddress,
311 active_code: ActiveCode,
312 user_def: Option<u32>,
313 ) -> Self {
314 Self {
315 dst_addr,
316 src_addr,
317 active_code,
318 reserved: Default::default(),
319 user_def,
320 }
321 }
322
323 #[inline]
325 const fn length() -> usize {
326 SIZE_OF_ADDRESS + SIZE_OF_ADDRESS + 1 + 4
327 }
328}
329
330impl TryFrom<&[u8]> for RoutingActive {
331 type Error = Error;
332 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
333 let (data_len, mut offset) = utils::data_len_check(data, Self::length(), false)?;
334 let dst_addr =
335 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
336 offset += SIZE_OF_ADDRESS;
337 let dst_addr = LogicAddress::from(dst_addr);
338 let src_addr =
339 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
340 offset += SIZE_OF_ADDRESS;
341 let src_addr = LogicAddress::from(src_addr);
342 let active = data[offset];
343 offset += 1;
344 let active_code = ActiveCode::from(active);
345 let reserved = u32::from_be_bytes(data[offset..offset + 4].try_into().unwrap());
346 offset += 4;
347 let user_def = match data_len - offset {
348 0 => Ok(None),
349 4 => Ok(Some(u32::from_be_bytes(
350 data[offset..offset + 4].try_into().unwrap(),
351 ))),
352 _ => Err(Error::InvalidLength {
353 actual: data_len,
354 expected: Self::length() + 4,
355 }),
356 }?;
357
358 Ok(Self {
359 dst_addr,
360 src_addr,
361 active_code,
362 reserved,
363 user_def,
364 })
365 }
366}
367
368impl From<RoutingActive> for Vec<u8> {
369 fn from(val: RoutingActive) -> Self {
370 let mut result = TCP_RESP_ROUTING_ACTIVE.to_be_bytes().to_vec();
371 let mut length = RoutingActive::length() as u32;
372 if val.user_def.is_some() {
373 length += 4;
374 }
375 result.extend(length.to_be_bytes());
376 let dst_addr: u16 = val.dst_addr.into();
377 result.extend(dst_addr.to_be_bytes());
378 let src_addr: u16 = val.src_addr.into();
379 result.extend(src_addr.to_be_bytes());
380 result.push(val.active_code.into());
381 result.extend(val.reserved.to_be_bytes());
382 if let Some(user_def) = val.user_def {
383 result.extend(user_def.to_be_bytes());
384 }
385
386 result
387 }
388}
389
390#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
391#[get_copy = "pub"]
392pub struct AliveCheck {
393 pub(crate) src_addr: LogicAddress,
395}
396
397impl AliveCheck {
398 pub fn new(addr: LogicAddress) -> Self {
399 Self { src_addr: addr }
400 }
401
402 #[inline]
403 const fn length() -> usize {
404 SIZE_OF_ADDRESS
405 }
406}
407
408impl TryFrom<&[u8]> for AliveCheck {
409 type Error = Error;
410 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
411 let (_, offset) = utils::data_len_check(data, Self::length(), true)?;
412 let src_addr = u16::from_be_bytes(data[offset..].try_into().unwrap());
413 let src_addr = LogicAddress::from(src_addr);
414
415 Ok(Self { src_addr })
416 }
417}
418
419impl From<AliveCheck> for Vec<u8> {
420 fn from(val: AliveCheck) -> Self {
421 let mut result = TCP_RESP_ALIVE_CHECK.to_be_bytes().to_vec();
422 let length = AliveCheck::length() as u32;
423 result.extend(length.to_be_bytes());
424 let src_addr: u16 = val.src_addr.into();
425 result.extend(src_addr.to_be_bytes());
426 result
427 }
428}
429
430#[derive(Debug, Clone, Eq, PartialEq, Getters)]
431#[get = "pub"]
432pub struct DiagnosticPositive {
433 #[getset(get_copy = "pub")]
435 pub(crate) src_addr: LogicAddress,
436 #[getset(get_copy = "pub")]
437 pub(crate) dst_addr: LogicAddress,
438 #[getset(get_copy = "pub")]
439 pub(crate) code: DiagnosticPositiveCode,
440 #[getset(get = "pub")]
442 pub(crate) pre_diag_data: Vec<u8>,
443}
444
445impl DiagnosticPositive {
446 pub fn new(
447 src_addr: LogicAddress,
448 dst_addr: LogicAddress,
449 code: DiagnosticPositiveCode,
450 pre_diag_data: Vec<u8>,
451 ) -> Self {
452 if code != DiagnosticPositiveCode::Confirm {
453 rsutil::warn!("Diagnostic Positive code: {:?}", code);
454 }
455 Self {
456 src_addr,
457 dst_addr,
458 code,
459 pre_diag_data,
460 }
461 }
462 #[inline]
464 const fn length() -> usize {
465 SIZE_OF_ADDRESS + SIZE_OF_ADDRESS + 1
466 }
467}
468
469impl TryFrom<&[u8]> for DiagnosticPositive {
470 type Error = Error;
471 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
472 let (_, mut offset) = utils::data_len_check(data, Self::length(), false)?;
473 let src_addr =
474 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
475 offset += SIZE_OF_ADDRESS;
476 let src_addr = LogicAddress::from(src_addr);
477 let dst_addr =
478 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
479 offset += SIZE_OF_ADDRESS;
480 let dst_addr = LogicAddress::from(dst_addr);
481 let code = DiagnosticPositiveCode::from(data[offset]);
482 offset += 1;
483 let pre_diag_msg = data[offset..].to_vec();
484
485 Ok(Self::new(src_addr, dst_addr, code, pre_diag_msg))
486 }
487}
488
489impl From<DiagnosticPositive> for Vec<u8> {
490 fn from(mut val: DiagnosticPositive) -> Self {
491 let mut result = TCP_RESP_DIAGNOSTIC_POSITIVE.to_be_bytes().to_vec();
492 let length = (DiagnosticPositive::length() + val.pre_diag_data.len()) as u32;
493 result.extend(length.to_be_bytes());
494 let src_addr: u16 = val.src_addr.into();
495 result.extend(src_addr.to_be_bytes());
496 let dst_addr: u16 = val.dst_addr.into();
497 result.extend(dst_addr.to_be_bytes());
498 result.push(val.code.into());
499 result.append(&mut val.pre_diag_data);
500
501 result
502 }
503}
504
505impl Display for DiagnosticPositive {
506 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
507 f.debug_struct("Diagnostic Positive")
508 .field("\n Source Address", &self.src_addr)
509 .field("\n Target Address", &self.dst_addr)
510 .field("\n Code", &self.code)
511 .field("\n Previous Data", &hex::encode(&self.pre_diag_data))
512 .finish()
513 }
514}
515
516#[derive(Debug, Clone, Eq, PartialEq, Getters, CopyGetters)]
517pub struct DiagnosticNegative {
518 #[getset(get_copy = "pub")]
520 pub(crate) src_addr: LogicAddress,
521 #[getset(get_copy = "pub")]
522 pub(crate) dst_addr: LogicAddress,
523 #[getset(get_copy = "pub")]
524 pub(crate) code: DiagnosticNegativeCode,
525 #[getset(get = "pub")]
527 pub(crate) pre_diag_data: Vec<u8>,
528}
529
530impl DiagnosticNegative {
531 pub fn new(
532 src_addr: LogicAddress,
533 dst_addr: LogicAddress,
534 code: DiagnosticNegativeCode,
535 pre_diag_data: Vec<u8>,
536 ) -> Self {
537 Self {
538 src_addr,
539 dst_addr,
540 code,
541 pre_diag_data,
542 }
543 }
544
545 #[inline]
547 const fn length() -> usize {
548 SIZE_OF_ADDRESS + SIZE_OF_ADDRESS + 1
549 }
550}
551
552impl TryFrom<&[u8]> for DiagnosticNegative {
553 type Error = Error;
554 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
555 let (_, mut offset) = utils::data_len_check(data, Self::length(), false)?;
556 let src_addr =
557 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
558 offset += SIZE_OF_ADDRESS;
559 let src_addr = LogicAddress::from(src_addr);
560 let dst_addr =
561 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
562 offset += SIZE_OF_ADDRESS;
563 let dst_addr = LogicAddress::from(dst_addr);
564 let code = DiagnosticNegativeCode::from(data[offset]);
565 offset += 1;
566 let pre_diag_data = data[offset..].to_vec();
567
568 Ok(Self {
569 src_addr,
570 dst_addr,
571 code,
572 pre_diag_data,
573 })
574 }
575}
576
577impl From<DiagnosticNegative> for Vec<u8> {
578 fn from(mut val: DiagnosticNegative) -> Self {
579 let mut result = TCP_RESP_DIAGNOSTIC_NEGATIVE.to_be_bytes().to_vec();
580 let length = (DiagnosticNegative::length() + val.pre_diag_data.len()) as u32;
581 result.extend(length.to_be_bytes());
582 let src_addr: u16 = val.src_addr.into();
583 result.extend(src_addr.to_be_bytes());
584 let dst_addr: u16 = val.dst_addr.into();
585 result.extend(dst_addr.to_be_bytes());
586 result.push(val.code.into());
587 result.append(&mut val.pre_diag_data);
588
589 result
590 }
591}
592
593impl Display for DiagnosticNegative {
594 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
595 f.debug_struct("Diagnostic Negative")
596 .field("\n Source Address", &self.src_addr)
597 .field("\n Target Address", &self.dst_addr)
598 .field("\n Code", &self.code)
599 .field("\n Previous Data", &hex::encode(&self.pre_diag_data))
600 .finish()
601 }
602}
603