can_types/
conversion.rs

1// Copyright (c) 2024 Nathan H. Keough
2//
3// This work is dual-licensed under MIT OR Apache 2.0 (or any later version).
4// You may choose between one of them if you use this work.
5//
6// For further detail, please refer to the individual licenses located at the root of this crate.
7
8//! Defines the standard conversion between units of data provided in this crate.
9
10use crate::{
11    payload::{Data, Name, Pdu},
12    protocol::{can2_a::identifier::IdCan2A, can2_b::identifier::IdCan2B},
13};
14
15if_alloc! {
16    use crate::alloc::string::String;
17}
18
19/// A trait for types that can be converted to and from bitfield representations (`bits`)
20/// of integers and hexadecimal string slices (hex).
21///
22/// #### `alloc` features:
23/// - `into_hex`
24pub trait Conversion<T>
25where
26    Self: Sized,
27{
28    type Error;
29
30    /// Convert an integer of type `T` into `Self`
31    fn from_bits(bits: T) -> Self;
32
33    /// Convert a hexadecimal string slice into `Self`
34    fn from_hex(hex_str: &str) -> Self;
35
36    /// Convert an integer of type `T` into `Self`
37    /// # Errors
38    /// - Implementation dependent
39    fn try_from_bits(bits: T) -> Result<Self, Self::Error>;
40
41    /// Convert a hexadecimal string slice into `Self`
42    /// # Errors
43    /// - Implementation dependent
44    fn try_from_hex(hex_str: &str) -> Result<Self, Self::Error>;
45
46    /// Convert `self` into an integer of type `T`
47    fn into_bits(self) -> T;
48
49    /// Convert `self` into a hexadecimal string
50    /// # Requires
51    /// - `alloc`
52    #[cfg(feature = "alloc")]
53    fn into_hex(self) -> String;
54}
55
56impl From<Pdu<Data>> for Pdu<Name> {
57    fn from(value: Pdu<Data>) -> Self {
58        Self::from_bits(value.into_bits())
59    }
60}
61
62impl From<Pdu<Name>> for Pdu<Data> {
63    fn from(value: Pdu<Name>) -> Self {
64        Self::from_bits(value.into_bits())
65    }
66}
67
68impl From<IdCan2A> for IdCan2B {
69    fn from(value: IdCan2A) -> Self {
70        Self::from_bits(value.into_bits().into())
71    }
72}
73
74#[cfg(test)]
75mod impl_tests {
76    use super::*;
77
78    #[test]
79    fn test_data_from() {
80        let name_a = Pdu::<Name>::from_hex("FFFF82DF1AFFFFFF");
81        let data_a = Pdu::<Data>::from(name_a);
82
83        assert_eq!(Pdu::<Data>::from_hex("FFFF82DF1AFFFFFF"), data_a);
84    }
85
86    #[test]
87    fn test_name_from() {
88        let data_a = Pdu::<Data>::from_hex("FFFF82DF1AFFFFFF");
89        let name_a = Pdu::<Name>::from(data_a);
90
91        assert_eq!(Pdu::<Name>::from_hex("FFFF82DF1AFFFFFF"), name_a);
92    }
93
94    #[test]
95    fn test_extended_from() {
96        let id_std_a = IdCan2A::from_hex("00F");
97        let id_ext_a = IdCan2B::from(id_std_a);
98
99        assert_eq!(IdCan2B::from_hex("0000000F"), id_ext_a);
100    }
101}