auto_uds/
utils.rs

1use core::fmt::Debug;
2
3/// A wrapper around a byte, which can be either an ISO-standardized value for a specific enum,
4/// or an implementation-specific/invalid `Extended` value wrapping original byte.
5#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
6#[deprecated(
7    note = "The `auto_uds` crate has been renamed to `automotive_diag`. Update your Cargo.toml, and use this enum from the `uds` namespace."
8)]
9pub enum ByteWrapper<T> {
10    Standard(T),
11    Extended(u8),
12}
13
14impl<T: Debug> Debug for ByteWrapper<T> {
15    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16        match self {
17            // For standard values, just delegate to the Debug implementation of the inner type.
18            Self::Standard(v) => Debug::fmt(v, f),
19            Self::Extended(v) => write!(f, "Extended({v:#02X})"),
20        }
21    }
22}
23
24impl<T: Into<u8>> From<ByteWrapper<T>> for u8 {
25    fn from(value: ByteWrapper<T>) -> Self {
26        match value {
27            ByteWrapper::Standard(v) => v.into(),
28            ByteWrapper::Extended(v) => v,
29        }
30    }
31}
32
33impl<T: TryFrom<u8>> From<u8> for ByteWrapper<T> {
34    fn from(value: u8) -> Self {
35        match T::try_from(value) {
36            Ok(v) => ByteWrapper::Standard(v),
37            Err(_) => ByteWrapper::Extended(value),
38        }
39    }
40}
41
42#[macro_export]
43macro_rules! enum_wrapper {
44    ($enum_name:tt, $enum_wrapper:tt) => {
45        #[doc = concat!("Store a single byte, either as a `Standard(", stringify!($enum_name), ")`, or as an `Extended(u8)`.")]
46        pub type $enum_wrapper = $crate::ByteWrapper<$enum_name>;
47
48        impl From<$crate::$enum_name> for $crate::$enum_wrapper {
49            fn from(value: $crate::$enum_name) -> Self {
50                Self::Standard(value)
51            }
52        }
53
54        #[cfg(test)]
55        mod tests {
56            #[test]
57            #[allow(non_snake_case)]
58            fn test_try_from() {
59                for value in 0x00_u8..=0xFF {
60                    if let Ok(v) = $crate::$enum_name::try_from(value) {
61                        let enc: u8 = v.into();
62                        assert_eq!(value, enc, "{value:#02X} → {v:?} → {enc:#02X}");
63                    }
64                }
65            }
66            #[test]
67            #[allow(non_snake_case)]
68            fn test_from() {
69                for value in 0x00_u8..=0xFF {
70                    let v = $crate::$enum_wrapper::from(value);
71                    let enc: u8 = v.into();
72                    assert_eq!(value, enc, "Wrapped {value:#02X} → {v:?} → {enc:#02X}");
73                }
74            }
75        }
76    };
77}