1use crate::{
2 error::Error,
3 frame::{
4 identifier::{Filter, Id},
5 Frame,
6 },
7 CanResult,
8};
9use derive_getters::Getters;
10use serde::{Deserialize, Serialize};
11use std::{
12 any::{type_name, Any},
13 collections::HashMap,
14 fmt::{self, Debug, Display},
15 hash::Hash,
16 sync::Weak,
17};
18
19#[async_trait::async_trait]
20pub trait Listener<C, F>: Send + Sync
21where
22 F: Frame,
23{
24 fn as_any(&self) -> &dyn Any;
25 async fn on_frame_transmitted(&self, channel: C, id: Id);
27 async fn on_frame_received(&self, frames: Weak<Vec<F>>);
29}
30
31#[async_trait::async_trait]
32pub trait Device: Send + Sync {
33 type Channel: Hash + Eq + Display + 'static;
34 type Frame: Frame<Channel = Self::Channel>;
35
36 fn new(builder: DeviceBuilder<Self::Channel>) -> CanResult<Self>
37 where
38 Self: Sized;
39
40 #[inline]
41 fn is_closed(&self) -> bool {
42 self.opened_channels().is_empty()
43 }
44 fn opened_channels(&self) -> Vec<Self::Channel>;
46 async fn transmit(&self, msg: Self::Frame, timeout: Option<u32>) -> CanResult<()>;
48 async fn receive(
50 &self,
51 channel: Self::Channel,
52 timeout: Option<u32>,
53 ) -> CanResult<Vec<Self::Frame>>;
54 fn shutdown(&mut self);
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
59pub enum ChannelMode {
60 Normal,
61 ListenOnly,
62 Loopback,
63 OneShot,
64}
65
66#[derive(Default, Deserialize, Serialize)]
67pub struct ChannelConfig {
68 pub nominal_bitrate: u32,
70 pub data_bitrate: Option<u32>,
72 pub termination: Option<bool>,
74 pub mode: Option<ChannelMode>,
76 pub recv_own_msg: Option<bool>,
78 pub filters: Vec<Filter>,
80 #[serde(skip)]
81 others: HashMap<String, Box<dyn Any + Send + Sync>>,
82}
83
84impl Debug for ChannelConfig {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 f.debug_struct("ChannelConfig")
87 .field("nominal_bitrate", &self.nominal_bitrate)
88 .field("data_bitrate", &self.data_bitrate)
89 .field("termination", &self.termination)
90 .field("mode", &self.mode)
91 .field("filters", &self.filters)
92 .finish_non_exhaustive()
93 }
94}
95
96impl ChannelConfig {
97 pub fn new(bitrate: u32) -> Self {
98 Self {
99 nominal_bitrate: bitrate,
100 ..Default::default()
101 }
102 }
103
104 pub fn set_data_bitrate(&mut self, bitrate: u32) -> &mut Self {
105 self.data_bitrate = Some(bitrate);
106 self
107 }
108
109 pub fn set_termination(&mut self, termination: bool) -> &mut Self {
110 self.termination = Some(termination);
111 self
112 }
113
114 pub fn set_channel_mode(&mut self, mode: ChannelMode) -> &mut Self {
115 self.mode = Some(mode);
116 self
117 }
118
119 pub fn set_recv_own_msg(&mut self, recv_own_msg: bool) -> &mut Self {
120 self.recv_own_msg = Some(recv_own_msg);
121 self
122 }
123
124 pub fn add_other(&mut self, name: &str, other: Box<dyn Any + Send + Sync>) -> &mut Self {
125 self.others.insert(name.into(), other);
126 self
127 }
128
129 pub fn get_other<T: Clone + 'static>(&self, name: &str) -> CanResult<Option<T>> {
130 get_other(&self.others, name)
131 }
132}
133
134#[derive(Default, Getters)]
135pub struct DeviceBuilder<K: Hash + Eq> {
136 #[getter(rename = "channel_configs")]
137 configs: HashMap<K, ChannelConfig>,
138 others: HashMap<String, Box<dyn Any + Send + Sync>>,
139}
140
141impl<K: Hash + Eq + Debug> Debug for DeviceBuilder<K> {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 f.debug_struct("DeviceBuilder")
144 .field("configs", &self.configs)
145 .finish_non_exhaustive()
146 }
147}
148
149impl<K: Hash + Eq + Default> DeviceBuilder<K> {
150 pub fn new() -> Self {
151 Self::default()
152 }
153
154 pub fn add_config(&mut self, channel: K, cfg: ChannelConfig) -> &mut Self {
155 self.configs.insert(channel.into(), cfg);
156 self
157 }
158
159 pub fn add_other(&mut self, name: &str, cfg: Box<dyn Any + Send + Sync>) -> &mut Self {
160 self.others.insert(name.into(), cfg);
161 self
162 }
163
164 pub fn get_other<T: Clone + 'static>(&self, name: &str) -> CanResult<Option<T>> {
165 get_other(&self.others, name)
166 }
167
168 pub fn build<T: Device<Channel = K>>(self) -> CanResult<T> {
169 T::new(self)
170 }
171}
172
173#[inline(always)]
174fn get_other<T: Clone + 'static>(
175 others: &HashMap<String, Box<dyn Any + Send + Sync>>,
176 name: &str,
177) -> CanResult<Option<T>> {
178 match others.get(name) {
179 Some(v) => Ok(Some(
180 v.downcast_ref::<T>()
181 .ok_or(Error::OtherError(format!(
182 "type mismatched for `{}` expected: `{}`",
183 name,
184 type_name::<T>()
185 )))?
186 .clone(),
187 )),
188 None => Ok(None),
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use super::*;
195
196 #[test]
197 fn get_other_returns_inserted_value() {
198 let mut builder = DeviceBuilder::<u8>::new();
199 builder.add_other("answer", Box::new(42_u32));
200
201 let value = builder.get_other::<u32>("answer").unwrap();
202 assert_eq!(value, Some(42));
203 }
204
205 #[test]
206 fn get_other_reports_type_mismatch() {
207 let mut builder = DeviceBuilder::<u8>::new();
208 builder.add_other("answer", Box::new(42_u32));
209
210 let err = builder.get_other::<String>("answer").unwrap_err();
211 assert!(matches!(err, Error::OtherError(_)));
212 }
213}