Skip to main content

zencan_common/
traits.rs

1//! Common traits
2
3use core::time::Duration;
4
5use arbitrary_int::{i24, u24};
6
7use crate::messages::CanMessage;
8
9/// A trait for computing the read size of some types
10pub trait ReadSize {
11    /// Read size of the type
12    const READ_SIZE: usize;
13}
14
15macro_rules! impl_read_size_builtin {
16    ($($rust_type:ty),+ $(,)?) => {
17        $(
18            impl ReadSize for $rust_type {
19                const READ_SIZE: usize = core::mem::size_of::<$rust_type>();
20            }
21        )+
22    };
23}
24impl_read_size_builtin!(bool, u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
25
26macro_rules! impl_read_size_arbitrary {
27    ($($rust_type:ty),+ $(,)?) => {
28        $(
29            impl ReadSize for $rust_type {
30                const READ_SIZE: usize = <$rust_type>::BITS.div_ceil(8);
31            }
32        )+
33    };
34}
35impl_read_size_arbitrary!(u24, i24);
36
37/// A trait for accessing a value
38///
39/// E.g. from an AtomicCell
40pub trait LoadStore<T> {
41    /// Read the value
42    fn load(&self) -> T;
43    /// Store a new value to the
44    fn store(&self, value: T);
45}
46
47/// A synchronous can sender
48pub trait CanSender {
49    /// Send a message to the bus
50    fn send(&mut self, msg: CanMessage) -> Result<(), CanMessage>;
51}
52
53/// A synchronous can receiver
54pub trait CanReceiver {
55    /// The error type returned by recv
56    type Error;
57    /// Attempt to read a message from the receiver, and return None immediately if no message is
58    /// available
59    fn try_recv(&mut self) -> Option<CanMessage>;
60    /// A blocking receive with timeout
61    fn recv(&mut self, timeout: Duration) -> Result<CanMessage, Self::Error>;
62}
63
64/// An async CAN sender trait
65pub trait AsyncCanSender: Send {
66    /// Error type returned by sender
67    type Error: CanSendError;
68    /// Send a message to the bus
69    fn send(
70        &mut self,
71        msg: CanMessage,
72    ) -> impl core::future::Future<Output = Result<(), Self::Error>>;
73}
74
75/// A trait for CAN errors which may come from different types of interfaces
76///
77/// On no_std, all the error can do is return the unsent frame. With `std`, it can convert any
78/// underlying errors into a String.
79pub trait CanSendError: core::fmt::Debug {
80    /// Convert the error into the undelivered message
81    fn into_can_message(self) -> CanMessage;
82
83    /// Get a string describing the error
84    #[cfg(feature = "std")]
85    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
86    fn message(&self) -> String;
87}
88
89/// An async CAN receiver trait
90pub trait AsyncCanReceiver: Send {
91    /// The error type returned by recv
92    type Error: core::fmt::Debug + Send;
93
94    /// Receive available message immediately
95    fn try_recv(&mut self) -> Option<CanMessage>;
96
97    /// A blocking receive
98    fn recv(
99        &mut self,
100    ) -> impl core::future::Future<Output = Result<CanMessage, Self::Error>> + Send;
101
102    /// Remove any pending messages from the receiver
103    fn flush(&mut self) {
104        while self.try_recv().is_some() {}
105    }
106}