1#![doc(html_root_url = "https://docs.rs/mini-slcan/0.1.1")]
4#![doc(test(attr(deny(unused_imports, unused_must_use))))]
6#![warn(missing_debug_implementations, rust_2018_idioms)]
7#![cfg_attr(not(test), no_std)]
8
9mod error;
10mod identifier;
11pub mod read;
12mod readme;
13pub mod write;
14
15pub use self::error::{Error, ErrorKind};
16pub use self::identifier::{ExtIdentifier, Identifier};
17
18use core::ops::{Deref, DerefMut};
19use defmt::Format;
20
21#[derive(Copy, Clone, Eq, PartialEq, Debug, Format)]
22pub enum Bitrate {
23 _10kbit,
24 _20kbit,
25 _50kbit,
26 _100kbit,
27 _125kbit,
28 _250kbit,
29 _500kbit,
30 _800kbit,
31 _1mbit,
32}
33
34impl Bitrate {
35 pub fn kbps(&self) -> u16 {
36 match self {
37 Bitrate::_10kbit => 10,
38 Bitrate::_20kbit => 20,
39 Bitrate::_50kbit => 50,
40 Bitrate::_100kbit => 100,
41 Bitrate::_125kbit => 125,
42 Bitrate::_250kbit => 250,
43 Bitrate::_500kbit => 500,
44 Bitrate::_800kbit => 800,
45 Bitrate::_1mbit => 1_000,
46 }
47 }
48}
49
50bitflags::bitflags! {
51 #[derive(Format)]
53 pub struct Status: u8 {
54 const RX_FIFO_FULL = 1 << 0;
55 const TX_FIFO_FULL = 1 << 1;
56 const ERROR_WARNING = 1 << 2;
57 const DATA_OVERRUN = 1 << 3;
58 const ERROR_PASSIVE = 1 << 5;
60 const ARBITRATION_LOST = 1 << 6;
61 const BUS_ERROR = 1 << 7;
62 }
63}
64
65#[derive(Copy, Clone, Eq, PartialEq, Debug, Format)]
67pub struct SerialNumber([u8; 4]);
68
69impl SerialNumber {
70 pub fn new(raw: [u8; 4]) -> Option<Self> {
74 if raw.iter().all(|b| b.is_ascii_alphanumeric()) {
75 Some(Self(raw))
76 } else {
77 None
78 }
79 }
80
81 pub const fn new_const(raw: [u8; 4]) -> Self {
82 let valid = raw[0].is_ascii_alphanumeric()
83 && raw[1].is_ascii_alphanumeric()
84 && raw[2].is_ascii_alphanumeric()
85 && raw[3].is_ascii_alphanumeric();
86
87 if !valid {
88 let serial_number_contain_non_alphanumeric_characters = ();
89
90 #[allow(unconditional_panic)]
91 [serial_number_contain_non_alphanumeric_characters][1];
92 }
93
94 Self(raw)
95 }
96}
97
98#[derive(Eq, PartialEq, Copy, Clone, Debug, Default)]
99pub struct CanFrame {
100 data: [u8; Self::MAX_LENGTH],
101 len: u8,
102}
103
104impl CanFrame {
105 pub const MAX_LENGTH: usize = 8;
106
107 #[inline]
108 pub const fn new() -> Self {
109 Self {
110 data: [0; Self::MAX_LENGTH],
111 len: 0,
112 }
113 }
114
115 #[inline]
116 pub fn len(&self) -> usize {
117 self.len.into()
118 }
119
120 #[inline]
121 pub fn data(&self) -> &[u8] {
122 &self.data[..usize::from(self.len)]
123 }
124
125 #[inline]
126 pub fn data_mut(&mut self) -> &mut [u8] {
127 &mut self.data[..usize::from(self.len)]
128 }
129
130 pub fn push(&mut self, byte: u8) -> Result<(), Error> {
134 if self.len() == Self::MAX_LENGTH {
135 Err(Error::eof())
136 } else {
137 self.data[self.len()] = byte;
138 self.len += 1;
139 Ok(())
140 }
141 }
142}
143
144impl Deref for CanFrame {
145 type Target = [u8];
146
147 fn deref(&self) -> &[u8] {
148 self.data()
149 }
150}
151
152impl DerefMut for CanFrame {
153 fn deref_mut(&mut self) -> &mut [u8] {
154 self.data_mut()
155 }
156}
157
158impl Format for CanFrame {
159 fn format(&self, fmt: &mut defmt::Formatter) {
160 self.data().format(fmt)
161 }
162}
163
164macro_rules! impl_from {
165 ( $($len:literal),+ ) => {
166 $(
167 impl From<[u8; $len]> for CanFrame {
168 fn from(arr: [u8; $len]) -> Self {
169 let mut data = [0; Self::MAX_LENGTH];
170 data[..$len].copy_from_slice(&arr);
171 Self {
172 data,
173 len: $len,
174 }
175 }
176 }
177 )+
178 };
179}
180
181impl_from!(0, 1, 2, 3, 4, 5, 6, 7, 8);