1use crate::{constants::*, error::Error, request, response, utils, PayloadType};
2use getset::{CopyGetters, Getters};
3use std::fmt::{Display, Formatter};
4
5#[repr(u8)]
7#[derive(Debug, Copy, Clone, Eq, Default, PartialEq)]
8pub enum Version {
9 ISO13400_2_2010 = 0x01,
10 ISO13400_2_2012 = 0x02,
11 ISO13400_2_2019 = 0x03,
12 Reserved(u8),
13 #[default]
14 Default = 0xFF,
15}
16
17impl From<Version> for u8 {
18 fn from(val: Version) -> Self {
19 match val {
20 Version::ISO13400_2_2010 => 0x01,
21 Version::ISO13400_2_2012 => 0x02,
22 Version::ISO13400_2_2019 => 0x03,
23 Version::Default => 0xFF,
24 Version::Reserved(v) => v,
25 }
26 }
27}
28
29impl From<Version> for Vec<u8> {
30 fn from(val: Version) -> Self {
31 let version: u8 = val.into();
32 vec![version, !version]
33 }
34}
35
36impl From<u8> for Version {
37 fn from(version: u8) -> Self {
38 match version {
39 0x01 => Self::ISO13400_2_2010,
40 0x02 => Self::ISO13400_2_2012,
41 0x03 => Self::ISO13400_2_2019,
42 0xFF => Self::Default,
43 _ => {
44 rsutil::warn!("ISO 13400-2 - used reserved version: {}", version);
45 Self::Reserved(version)
46 }
47 }
48 }
49}
50
51impl TryFrom<&[u8]> for Version {
52 type Error = Error;
53 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
54 let data_len = data.len();
55 if data_len < SIZE_OF_VERSION {
56 return Err(Error::InvalidLength {
57 actual: data_len,
58 expected: SIZE_OF_VERSION,
59 });
60 }
61
62 let version = data[0];
63 let reverse = data[1];
64 if !version != reverse {
65 return Err(Error::InvalidVersion { version, reverse });
66 }
67
68 Ok(Self::from(version))
69 }
70}
71
72#[repr(u8)]
74#[derive(Debug, Copy, Clone, Eq, PartialEq)]
75pub enum HeaderNegativeCode {
76 IncorrectPatternFormat = 0x00, UnknownPayloadTYpe = 0x01,
78 MessageTooLarge = 0x02,
79 OutOfMemory = 0x03,
80 InvalidPayloadLength = 0x04, Reserved(u8),
82}
83
84impl From<HeaderNegativeCode> for u8 {
85 fn from(val: HeaderNegativeCode) -> Self {
86 match val {
87 HeaderNegativeCode::IncorrectPatternFormat => 0x00,
88 HeaderNegativeCode::UnknownPayloadTYpe => 0x01,
89 HeaderNegativeCode::MessageTooLarge => 0x02,
90 HeaderNegativeCode::OutOfMemory => 0x03,
91 HeaderNegativeCode::InvalidPayloadLength => 0x04,
92 HeaderNegativeCode::Reserved(code) => code,
93 }
94 }
95}
96
97impl From<u8> for HeaderNegativeCode {
98 fn from(code: u8) -> Self {
99 match code {
100 0x00 => Self::IncorrectPatternFormat,
101 0x01 => Self::UnknownPayloadTYpe,
102 0x02 => Self::MessageTooLarge,
103 0x03 => Self::OutOfMemory,
104 0x04 => Self::InvalidPayloadLength,
105 _ => {
106 rsutil::warn!("ISO 13400-2 - used reserved header negative code: {}", code);
107 Self::Reserved(code)
108 }
109 }
110 }
111}
112
113#[repr(u8)]
144#[derive(Debug, Copy, Clone, Eq, PartialEq)]
145pub enum LogicAddress {
146 VMSpecific(u16), Client(u16), VMSpecificFunctional(u16), Reserved(u16), }
151
152impl From<u16> for LogicAddress {
153 fn from(v: u16) -> Self {
154 match v {
155 0x0001..=0x0DFF | 0x1000..=0x7FFF => Self::VMSpecific(v),
156 0x0E00..=0x0FFF => Self::Client(v),
157 0xE400..=0xEFFF => Self::VMSpecificFunctional(v),
158 _ => {
159 rsutil::warn!("ISO 13400-2 - used reserved logic address: {}", v);
160 Self::Reserved(v)
161 }
162 }
163 }
164}
165
166impl From<LogicAddress> for u16 {
167 fn from(val: LogicAddress) -> Self {
168 match val {
169 LogicAddress::VMSpecific(v) => v,
170 LogicAddress::Client(v) => v,
171 LogicAddress::VMSpecificFunctional(v) => v,
172 LogicAddress::Reserved(v) => v,
173 }
174 }
175}
176
177impl Display for LogicAddress {
178 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
179 let value: u16 = (*self).into();
180 write!(f, "{:#X}", value)
181 }
182}
183
184#[repr(u8)]
186#[derive(Debug, Copy, Clone, Eq, PartialEq)]
187pub enum NodeType {
188 Gateway = 0x00,
189 Node = 0x01,
190 Reserved(u8),
191}
192
193impl From<NodeType> for u8 {
194 fn from(val: NodeType) -> Self {
195 match val {
196 NodeType::Gateway => 0x00,
197 NodeType::Node => 0x01,
198 NodeType::Reserved(v) => v,
199 }
200 }
201}
202
203impl From<u8> for NodeType {
204 fn from(v: u8) -> Self {
205 match v {
206 0x00 => Self::Gateway,
207 0x01 => Self::Node,
208 _ => {
209 rsutil::warn!("ISO 13400-2 - used reserved entity: {}", v);
210 Self::Reserved(v)
211 }
212 }
213 }
214}
215
216impl Display for NodeType {
217 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
218 match self {
219 NodeType::Gateway => write!(f, "Gateway"),
220 NodeType::Node => write!(f, "Node"),
221 NodeType::Reserved(v) => write!(f, "{}", format_args!("Unknown({:#X})", *v)),
222 }
223 }
224}
225
226#[repr(u8)]
228#[derive(Debug, Copy, Clone, Eq, PartialEq)]
229pub enum FurtherAction {
230 NoAction = 0x00,
231 Reserved(u8), CentralSecurity = 0x10,
233 VMSpecific(u8), }
235
236impl From<FurtherAction> for u8 {
237 fn from(val: FurtherAction) -> Self {
238 match val {
239 FurtherAction::NoAction => 0x00,
240 FurtherAction::Reserved(v) => v,
241 FurtherAction::CentralSecurity => 0x10,
242 FurtherAction::VMSpecific(v) => v,
243 }
244 }
245}
246
247impl From<u8> for FurtherAction {
248 fn from(v: u8) -> Self {
249 match v {
250 0x00 => Self::NoAction,
251 0x01..=0x0F => {
252 rsutil::warn!("ISO 13400-2 - used reserved further action: {}", v);
253 Self::Reserved(v)
254 }
255 0x10 => Self::CentralSecurity,
256 _ => Self::VMSpecific(v),
257 }
258 }
259}
260
261#[repr(u8)]
263#[derive(Debug, Copy, Clone, Eq, PartialEq)]
264pub enum SyncStatus {
265 VINorGIDSync = 0x00,
266 VINorGIDNotSync = 0x10,
267 Reserved(u8),
268}
269
270impl From<SyncStatus> for u8 {
271 fn from(val: SyncStatus) -> Self {
272 match val {
273 SyncStatus::VINorGIDSync => 0x00,
274 SyncStatus::VINorGIDNotSync => 0x10,
275 SyncStatus::Reserved(v) => v,
276 }
277 }
278}
279
280impl From<u8> for SyncStatus {
281 fn from(v: u8) -> Self {
282 match v {
283 0x00 => Self::VINorGIDSync,
284 0x10 => Self::VINorGIDNotSync,
285 _ => {
286 rsutil::warn!("ISO 13400-2 - used reserved VIN/GID sync. status: {}", v);
287 Self::Reserved(v)
288 }
289 }
290 }
291}
292
293#[repr(u8)]
295#[derive(Debug, Copy, Clone, Eq, PartialEq)]
296pub enum ActiveCode {
297 SourceAddressUnknown = 0x00, Activated = 0x01, SourceAddressInvalid = 0x02, SocketInvalid = 0x03, WithoutAuth = 0x04,
302 VehicleRefused = 0x05, Unsupported = 0x06, TLSRequired = 0x07,
306 Success = 0x10,
307 NeedConfirm = 0x11,
308 VMSpecific(u8), Reserved(u8), }
311
312impl From<ActiveCode> for u8 {
313 fn from(val: ActiveCode) -> Self {
314 match val {
315 ActiveCode::SourceAddressUnknown => 0x00,
316 ActiveCode::Activated => 0x01,
317 ActiveCode::SourceAddressInvalid => 0x02,
318 ActiveCode::SocketInvalid => 0x03,
319 ActiveCode::WithoutAuth => 0x04,
320 ActiveCode::VehicleRefused => 0x05,
321 ActiveCode::Unsupported => 0x06,
322 ActiveCode::TLSRequired => 0x07,
323 ActiveCode::Success => 0x10,
324 ActiveCode::NeedConfirm => 0x11,
325 ActiveCode::VMSpecific(v) => v,
326 ActiveCode::Reserved(v) => v,
327 }
328 }
329}
330
331impl From<u8> for ActiveCode {
332 fn from(v: u8) -> Self {
333 match v {
334 0x00 => Self::SourceAddressUnknown,
335 0x01 => Self::Activated,
336 0x02 => Self::SourceAddressInvalid,
337 0x03 => Self::SocketInvalid,
338 0x04 => Self::WithoutAuth,
339 0x05 => Self::VehicleRefused,
340 0x06 => Self::Unsupported,
341 0x07 => Self::TLSRequired,
342 0x10 => Self::Success,
343 0x11 => Self::NeedConfirm,
344 0xE0..=0xFE => Self::VMSpecific(v),
345 _ => {
346 rsutil::warn!("ISO 13400-2 - used reserved active code: {}", v);
347 Self::Reserved(v)
348 }
349 }
350 }
351}
352
353#[repr(u8)]
355#[derive(Debug, Copy, Clone, Eq, PartialEq)]
356pub enum PowerMode {
357 NotReady = 0x00,
358 Ready = 0x01,
359 NotSupported = 0x02,
360 Reserved(u8),
361}
362
363impl From<PowerMode> for u8 {
364 fn from(val: PowerMode) -> Self {
365 match val {
366 PowerMode::NotReady => 0x00,
367 PowerMode::Ready => 0x01,
368 PowerMode::NotSupported => 0x02,
369 PowerMode::Reserved(v) => v,
370 }
371 }
372}
373
374impl From<u8> for PowerMode {
375 fn from(v: u8) -> Self {
376 match v {
377 0x00 => Self::NotReady,
378 0x01 => Self::Ready,
379 0x02 => Self::NotSupported,
380 _ => {
381 rsutil::warn!("ISO 13400-2 - used reserved power mode: {}", v);
382 Self::Reserved(v)
383 }
384 }
385 }
386}
387
388#[repr(u8)]
390#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
391pub enum RoutingActiveType {
392 #[default]
393 Default = 0x00,
394 WWHODB = 0x01,
395 Reserved(u8), CentralSecurity = 0xE0,
397 VMSpecific(u8), }
399
400impl From<RoutingActiveType> for u8 {
401 fn from(val: RoutingActiveType) -> Self {
402 match val {
403 RoutingActiveType::Default => 0x00,
404 RoutingActiveType::WWHODB => 0x01,
405 RoutingActiveType::Reserved(v) => v,
406 RoutingActiveType::CentralSecurity => 0xE0,
407 RoutingActiveType::VMSpecific(v) => v,
408 }
409 }
410}
411
412impl From<u8> for RoutingActiveType {
413 fn from(v: u8) -> Self {
414 match v {
415 0x00 => Self::Default,
416 0x01 => Self::WWHODB,
417 0x02..=0xDF => {
418 rsutil::warn!("ISO 13400-2 - used reserved routing active type: {}", v);
419 Self::Reserved(v)
420 }
421 0xE0 => Self::CentralSecurity,
422 _ => Self::VMSpecific(v),
423 }
424 }
425}
426
427#[repr(u8)]
429#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
430pub enum DiagnosticPositiveCode {
431 #[default]
432 Confirm = 0x00,
433 Reserved(u8),
434}
435
436impl From<DiagnosticPositiveCode> for u8 {
437 fn from(val: DiagnosticPositiveCode) -> Self {
438 match val {
439 DiagnosticPositiveCode::Confirm => 0x00,
440 DiagnosticPositiveCode::Reserved(v) => v,
441 }
442 }
443}
444
445impl From<u8> for DiagnosticPositiveCode {
446 fn from(v: u8) -> Self {
447 match v {
448 0x00 => Self::Confirm,
449 _ => {
450 rsutil::warn!(
451 "ISO 13400-2 - used reserved diagnostic positive code: {}",
452 v
453 );
454 Self::Reserved(v)
455 }
456 }
457 }
458}
459
460impl Display for DiagnosticPositiveCode {
461 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
462 match self {
463 Self::Confirm => write!(f, "Diagnostic Positive Confirm"),
464 Self::Reserved(v) => write!(f, "Diagnostic Positive Reserved({})", v),
465 }
466 }
467}
468
469#[repr(u8)]
471#[derive(Debug, Copy, Clone, Eq, PartialEq)]
472pub enum DiagnosticNegativeCode {
473 InvalidSourceAddress = 0x02,
474 UnknownTargetAddress = 0x03,
475 DiagnosticMessageTooLarge = 0x04,
476 OutOfMemory = 0x05,
477 TargetUnreachable = 0x06,
478 UnknownNetwork = 0x07,
479 TransportProtocolError = 0x08,
480 Reserved(u8),
481}
482
483impl From<DiagnosticNegativeCode> for u8 {
484 fn from(val: DiagnosticNegativeCode) -> Self {
485 match val {
486 DiagnosticNegativeCode::InvalidSourceAddress => 0x02,
487 DiagnosticNegativeCode::UnknownTargetAddress => 0x03,
488 DiagnosticNegativeCode::DiagnosticMessageTooLarge => 0x04,
489 DiagnosticNegativeCode::OutOfMemory => 0x05,
490 DiagnosticNegativeCode::TargetUnreachable => 0x06,
491 DiagnosticNegativeCode::UnknownNetwork => 0x07,
492 DiagnosticNegativeCode::TransportProtocolError => 0x08,
493 DiagnosticNegativeCode::Reserved(v) => v,
494 }
495 }
496}
497
498impl From<u8> for DiagnosticNegativeCode {
499 fn from(v: u8) -> Self {
500 match v {
501 0x02 => Self::InvalidSourceAddress,
502 0x03 => Self::UnknownTargetAddress,
503 0x04 => Self::DiagnosticMessageTooLarge,
504 0x05 => Self::OutOfMemory,
505 0x06 => Self::TargetUnreachable,
506 0x07 => Self::UnknownNetwork,
507 0x08 => Self::TransportProtocolError,
508 _ => {
509 rsutil::warn!(
510 "ISO 13400-2 - used reserved diagnostic negative code: {}",
511 v
512 );
513 Self::Reserved(v)
514 }
515 }
516 }
517}
518
519impl Display for DiagnosticNegativeCode {
520 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
521 match self {
522 Self::InvalidSourceAddress => write!(f, "Diagnostic Negative Source Address"),
523 Self::UnknownTargetAddress => write!(f, "Diagnostic Negative Target Address"),
524 Self::DiagnosticMessageTooLarge => {
525 write!(f, "Diagnostic Negative Diagnostic Message Too Large")
526 }
527 Self::OutOfMemory => write!(f, "Diagnostic Negative Target Address"),
528 Self::TargetUnreachable => write!(f, "Diagnostic Negative Target Address"),
529 Self::UnknownNetwork => write!(f, "Diagnostic Negative Target Address"),
530 Self::TransportProtocolError => {
531 write!(f, "Diagnostic Negative Transport Protocol Error")
532 }
533 Self::Reserved(v) => write!(f, "Diagnostic Negative Reserved({})", v),
534 }
535 }
536}
537
538#[derive(Debug, Clone, Eq, PartialEq, Getters, CopyGetters)]
543pub struct Diagnostic {
544 #[getset(get_copy = "pub")]
546 pub(crate) dst_addr: LogicAddress,
547 #[getset(get_copy = "pub")]
548 pub(crate) src_addr: LogicAddress,
549 #[getset(get = "pub")]
550 pub data: Vec<u8>,
551}
552
553impl Diagnostic {
554 pub fn new(dst_addr: LogicAddress, src_addr: LogicAddress, data: Vec<u8>) -> Self {
555 Self {
556 dst_addr,
557 src_addr,
558 data,
559 }
560 }
561
562 #[inline]
564 const fn length() -> usize {
565 SIZE_OF_ADDRESS + SIZE_OF_ADDRESS
566 }
567}
568
569impl TryFrom<&[u8]> for Diagnostic {
570 type Error = Error;
571 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
572 let (_, mut offset) = utils::data_len_check(data, Self::length(), false)?;
573 let dst_addr =
574 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
575 offset += SIZE_OF_ADDRESS;
576 let dst_addr = LogicAddress::from(dst_addr);
577 let src_addr =
578 u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
579 offset += SIZE_OF_ADDRESS;
580 let src_addr = LogicAddress::from(src_addr);
581 let data = data[offset..].to_vec();
582
583 Ok(Self::new(dst_addr, src_addr, data))
584 }
585}
586
587impl From<Diagnostic> for Vec<u8> {
588 fn from(mut val: Diagnostic) -> Self {
589 let mut result = TCP_DIAGNOSTIC.to_be_bytes().to_vec();
590 let length = (Diagnostic::length() + val.data.len()) as u32;
591 result.extend(length.to_be_bytes());
592 let dst_addr: u16 = val.dst_addr.into();
593 result.extend(dst_addr.to_be_bytes());
594 let src_addr: u16 = val.src_addr.into();
595 result.extend(src_addr.to_be_bytes());
596 result.append(&mut val.data);
597
598 result
599 }
600}
601
602#[derive(Debug, Clone)]
604pub enum Payload {
605 RespHeaderNegative(response::HeaderNegative), ReqVehicleId(request::VehicleID), ReqVehicleWithEid(request::VehicleIDWithEID), ReqVehicleWithVIN(request::VehicleIDWithVIN), RespVehicleId(response::VehicleID), ReqRoutingActive(request::RoutingActive), RespRoutingActive(response::RoutingActive), ReqAliveCheck(request::AliveCheck), RespAliveCheck(response::AliveCheck), ReqEntityStatus(request::EntityStatus), ReqDiagPowerMode(request::DiagnosticPowerMode), RespEntityStatus(response::EntityStatus), RespDiagPowerMode(response::DiagnosticPowerMode), Diagnostic(Diagnostic), RespDiagPositive(response::DiagnosticPositive), RespDiagNegative(response::DiagnosticNegative), }
622
623impl Payload {
624 pub fn payload_type(&self) -> PayloadType {
625 match &self {
626 Payload::RespHeaderNegative(_) => PayloadType::RespHeaderNegative,
627 Payload::ReqVehicleId(_) => PayloadType::ReqVehicleId,
628 Payload::ReqVehicleWithEid(_) => PayloadType::ReqVehicleWithEid,
629 Payload::ReqVehicleWithVIN(_) => PayloadType::ReqVehicleWithVIN,
630 Payload::RespVehicleId(_) => PayloadType::RespVehicleId,
631 Payload::ReqRoutingActive(_) => PayloadType::ReqRoutingActive,
632 Payload::RespRoutingActive(_) => PayloadType::RespRoutingActive,
633 Payload::ReqAliveCheck(_) => PayloadType::ReqAliveCheck,
634 Payload::RespAliveCheck(_) => PayloadType::RespAliveCheck,
635 Payload::ReqEntityStatus(_) => PayloadType::ReqEntityStatus,
636 Payload::ReqDiagPowerMode(_) => PayloadType::ReqDiagPowerMode,
637 Payload::RespEntityStatus(_) => PayloadType::RespEntityStatus,
638 Payload::RespDiagPowerMode(_) => PayloadType::RespDiagPowerMode,
639 Payload::Diagnostic(_) => PayloadType::Diagnostic,
640 Payload::RespDiagPositive(_) => PayloadType::RespDiagPositive,
641 Payload::RespDiagNegative(_) => PayloadType::RespDiagNegative,
642 }
643 }
644}
645
646#[derive(Debug, Clone)]
647pub struct Message {
648 pub version: Version,
649 pub payload: Payload,
650}
651
652impl From<Message> for Vec<u8> {
653 fn from(val: Message) -> Self {
654 let mut result: Vec<_> = val.version.into();
655 match val.payload {
656 Payload::RespHeaderNegative(v) => result.append(&mut v.into()),
657 Payload::ReqVehicleId(v) => result.append(&mut v.into()),
658 Payload::ReqVehicleWithEid(v) => result.append(&mut v.into()),
659 Payload::ReqVehicleWithVIN(v) => result.append(&mut v.into()),
660 Payload::RespVehicleId(v) => result.append(&mut v.into()),
661 Payload::ReqRoutingActive(v) => result.append(&mut v.into()),
662 Payload::RespRoutingActive(v) => result.append(&mut v.into()),
663 Payload::ReqAliveCheck(v) => result.append(&mut v.into()),
664 Payload::RespAliveCheck(v) => result.append(&mut v.into()),
665 Payload::ReqEntityStatus(v) => result.append(&mut v.into()),
666 Payload::ReqDiagPowerMode(v) => result.append(&mut v.into()),
667 Payload::RespEntityStatus(v) => result.append(&mut v.into()),
668 Payload::RespDiagPowerMode(v) => result.append(&mut v.into()),
669 Payload::Diagnostic(v) => result.append(&mut v.into()),
670 Payload::RespDiagPositive(v) => result.append(&mut v.into()),
671 Payload::RespDiagNegative(v) => result.append(&mut v.into()),
672 }
673
674 result
675 }
676}
677
678impl TryFrom<&[u8]> for Message {
679 type Error = Error;
680 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
681 rsutil::debug!("ISO 13400-2 - parsing data: {}", hex::encode(data));
682 let data_len = data.len();
683 let expected = SIZE_OF_VERSION + SIZE_OF_DATA_TYPE + SIZE_OF_LENGTH;
684 if data_len < expected {
685 return Err(Error::InvalidLength {
686 actual: data_len,
687 expected,
688 });
689 }
690
691 let mut offset = 0;
692 let version = Version::try_from(data)?;
693 offset += SIZE_OF_VERSION;
694 let payload_type =
695 u16::from_be_bytes(data[offset..offset + SIZE_OF_DATA_TYPE].try_into().unwrap());
696 offset += SIZE_OF_DATA_TYPE;
697 let payload_len =
698 u32::from_be_bytes(data[offset..offset + SIZE_OF_LENGTH].try_into().unwrap());
699 offset += SIZE_OF_LENGTH;
700 let expected = data_len - offset;
701 if (payload_len as usize) != expected {
702 return Err(Error::InvalidPayloadLength {
703 actual: payload_len as usize,
704 expected,
705 });
706 }
707 let payload = match PayloadType::try_from(payload_type)? {
708 PayloadType::RespHeaderNegative => {
709 Payload::RespHeaderNegative(response::HeaderNegative::try_from(&data[offset..])?)
710 }
711 PayloadType::ReqVehicleId => {
712 Payload::ReqVehicleId(request::VehicleID::try_from(&data[offset..])?)
713 }
714 PayloadType::ReqVehicleWithEid => {
715 Payload::ReqVehicleWithEid(request::VehicleIDWithEID::try_from(&data[offset..])?)
716 }
717 PayloadType::ReqVehicleWithVIN => {
718 Payload::ReqVehicleWithVIN(request::VehicleIDWithVIN::try_from(&data[offset..])?)
719 }
720 PayloadType::RespVehicleId => {
721 Payload::RespVehicleId(response::VehicleID::try_from(&data[offset..])?)
722 }
723 PayloadType::ReqRoutingActive => {
724 Payload::ReqRoutingActive(request::RoutingActive::try_from(&data[offset..])?)
725 }
726 PayloadType::RespRoutingActive => {
727 Payload::RespRoutingActive(response::RoutingActive::try_from(&data[offset..])?)
728 }
729 PayloadType::ReqAliveCheck => {
730 Payload::ReqAliveCheck(request::AliveCheck::try_from(&data[offset..])?)
731 }
732 PayloadType::RespAliveCheck => {
733 Payload::RespAliveCheck(response::AliveCheck::try_from(&data[offset..])?)
734 }
735 PayloadType::ReqEntityStatus => {
736 Payload::ReqEntityStatus(request::EntityStatus::try_from(&data[offset..])?)
737 }
738 PayloadType::RespEntityStatus => {
739 Payload::RespEntityStatus(response::EntityStatus::try_from(&data[offset..])?)
740 }
741 PayloadType::ReqDiagPowerMode => {
742 Payload::ReqDiagPowerMode(request::DiagnosticPowerMode::try_from(&data[offset..])?)
743 }
744 PayloadType::RespDiagPowerMode => Payload::RespDiagPowerMode(
745 response::DiagnosticPowerMode::try_from(&data[offset..])?,
746 ),
747 PayloadType::Diagnostic => Payload::Diagnostic(Diagnostic::try_from(&data[offset..])?),
748 PayloadType::RespDiagPositive => {
749 Payload::RespDiagPositive(response::DiagnosticPositive::try_from(&data[offset..])?)
750 }
751 PayloadType::RespDiagNegative => {
752 Payload::RespDiagNegative(response::DiagnosticNegative::try_from(&data[offset..])?)
753 }
754 };
755
756 Ok(Self { version, payload })
757 }
758}