rs_can/frame/
mod.rs

1mod identifier;
2pub use identifier::*;
3
4use std::fmt::{Display, Formatter, Write};
5use crate::utils::can_dlc;
6
7#[repr(C)]
8#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
9pub enum Type {
10    #[default]
11    Can,
12    CanFd,
13    CanXl,
14}
15
16#[repr(C)]
17#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
18pub enum Direct {
19    #[default]
20    Transmit,
21    Receive,
22}
23
24impl Display for Direct {
25    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
26        match self {
27            Self::Transmit => f.write_str("Tx"),
28            Self::Receive => f.write_str("Rx"),
29        }
30    }
31}
32
33/// CAN 2.0 | CAN 1.0
34pub trait Frame: Send + Sync {
35    type Channel: Display;
36
37    fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self>
38    where
39        Self: Sized;
40
41    fn new_remote(id: impl Into<Id>, len: usize) -> Option<Self>
42    where
43        Self: Sized;
44
45    fn timestamp(&self) -> u64;
46
47    fn set_timestamp(&mut self, value: Option<u64>) -> &mut Self
48    where
49        Self: Sized;
50
51    /// Prioritizes returning J1939Id if j1939 is true.
52    fn id(&self) -> Id;
53
54    fn can_type(&self) -> Type;
55
56    fn set_can_type(&mut self, r#type: Type) -> &mut Self
57    where
58        Self: Sized;
59
60    fn is_remote(&self) -> bool;
61
62    fn is_extended(&self) -> bool;
63
64    fn direct(&self) -> Direct;
65
66    fn set_direct(&mut self, direct: Direct) -> &mut Self
67    where
68        Self: Sized;
69
70    fn is_bitrate_switch(&self) -> bool;
71
72    fn set_bitrate_switch(&mut self, value: bool) -> &mut Self
73    where
74        Self: Sized;
75
76    fn is_error_frame(&self) -> bool;
77
78    fn set_error_frame(&mut self, value: bool) -> &mut Self
79    where
80        Self: Sized;
81
82    /// Error state indicator
83    fn is_esi(&self) -> bool;
84
85    /// Set error state indicator
86    fn set_esi(&mut self, value: bool) -> &mut Self
87    where
88        Self: Sized;
89
90    fn channel(&self) -> Self::Channel;
91
92    fn set_channel(&mut self, value: Self::Channel) -> &mut Self
93    where
94        Self: Sized;
95
96    /// ensure return the actual length of data.
97    fn data(&self) -> &[u8];
98
99    fn dlc(&self) -> isize {
100        can_dlc(self.length(), self.can_type())
101    }
102
103    fn length(&self) -> usize;
104}
105
106impl<T: Display> Display for dyn Frame<Channel = T> {
107    /// Output Frame as `asc` String.
108    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
109        let data_str = if self.is_remote() {
110            " ".to_owned()
111        } else {
112            self.data()
113                .iter()
114                .fold(String::new(), |mut out, &b| {
115                    let _ = write!(out, "{b:02x} ");
116                    out
117                })
118        };
119
120        match self.can_type() {
121            Type::Can => {
122                write!(f, "{:.3} {} {}{: <4} {} {} {} {}",
123                       self.timestamp() as f64 / 1000.,
124                       self.channel(),
125                       format!("{: >8x}", self.id().into_bits()),
126                       if self.is_extended() { "x" } else { "" },
127                       self.direct(),
128                       // if self.is_rx() { "Rx" } else { "Tx" },
129                       if self.is_remote() { "r" } else { "d" },
130                       format!("{: >2}", self.length()),
131                       data_str,
132                )
133            },
134            Type::CanFd => {
135                let mut flags = 1 << 12;
136                write!(f, "{:.3} CANFD {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}",
137                       self.timestamp() as f64 / 1000.,
138                       self.channel(),
139                       self.direct(),
140                       // if self.is_rx() { "Rx" } else { "Tx" },
141                       format!("{: >8x}", self.id().into_bits()),
142                       if self.is_bitrate_switch() {
143                           flags |= 1 << 13;
144                           1
145                       } else { 0 },
146                       if self.is_esi() {
147                           flags |= 1 << 14;
148                           1
149                       } else { 0 },
150                       format!("{: >2}", self.dlc()),
151                       format!("{: >2}", self.length()),
152                       data_str,
153                       format!("{: >8}", 0),       // message_duration
154                       format!("{: <4}", 0),       // message_length
155                       format!("{: >8x}", flags),
156                       format!("{: >8}", 0),       // crc
157                       format!("{: >8}", 0),       // bit_timing_conf_arb
158                       format!("{: >8}", 0),       // bit_timing_conf_data
159                       format!("{: >8}", 0),       // bit_timing_conf_ext_arb
160                       format!("{: >8}", 0),       // bit_timing_conf_ext_data
161                )
162            },
163            Type::CanXl => {    // TODO
164                write!(f, "CANXL Frame")
165            }
166        }
167    }
168}