#[cfg(test)]
mod tests;
use core::cmp::Ordering;
use core::ops::{Deref, DerefMut};
use crate::{Id, IdReg};
#[derive(Clone, Debug, Eq)]
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
pub struct Frame {
pub(crate) id: IdReg,
pub(crate) data: Data,
}
impl Frame {
pub fn new_data(id: impl Into<Id>, data: impl Into<Data>) -> Self {
let id = match id.into() {
Id::Standard(id) => IdReg::new_standard(id),
Id::Extended(id) => IdReg::new_extended(id),
};
Self {
id,
data: data.into(),
}
}
pub fn new_remote(id: impl Into<Id>, dlc: u8) -> Self {
assert!(dlc <= 8);
let mut frame = Self::new_data(id, []);
frame.data.len = dlc;
frame.id = frame.id.with_rtr(true);
frame
}
#[inline]
pub fn is_extended(&self) -> bool {
self.id.is_extended()
}
#[inline]
pub fn is_standard(&self) -> bool {
self.id.is_standard()
}
#[inline]
pub fn is_remote_frame(&self) -> bool {
self.id.rtr()
}
#[inline]
pub fn is_data_frame(&self) -> bool {
!self.is_remote_frame()
}
#[inline]
pub fn id(&self) -> Id {
self.id.to_id()
}
#[inline]
pub fn priority(&self) -> FramePriority {
FramePriority(self.id)
}
#[inline]
pub fn dlc(&self) -> u8 {
self.data.len() as u8
}
pub fn data(&self) -> Option<&Data> {
if self.is_data_frame() {
Some(&self.data)
} else {
None
}
}
}
impl PartialEq for Frame {
fn eq(&self, other: &Self) -> bool {
match (self.data(), other.data()) {
(None, None) => self.id.eq(&other.id),
(Some(a), Some(b)) => self.id.eq(&other.id) && a.eq(b),
(None, Some(_)) | (Some(_), None) => false,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct FramePriority(IdReg);
impl Ord for FramePriority {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl PartialOrd for FramePriority {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for FramePriority {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for FramePriority {}
#[derive(Debug, Copy, Clone)]
pub struct Data {
pub(crate) len: u8,
pub(crate) bytes: [u8; 8],
}
impl Data {
pub fn new(data: &[u8]) -> Option<Self> {
if data.len() > 8 {
return None;
}
let mut bytes = [0; 8];
bytes[..data.len()].copy_from_slice(data);
Some(Self {
len: data.len() as u8,
bytes,
})
}
#[inline]
pub const fn empty() -> Self {
Self {
len: 0,
bytes: [0; 8],
}
}
}
impl Deref for Data {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
&self.bytes[..usize::from(self.len)]
}
}
impl DerefMut for Data {
#[inline]
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..usize::from(self.len)]
}
}
impl AsRef<[u8]> for Data {
#[inline]
fn as_ref(&self) -> &[u8] {
self.deref()
}
}
impl AsMut<[u8]> for Data {
#[inline]
fn as_mut(&mut self) -> &mut [u8] {
self.deref_mut()
}
}
impl PartialEq for Data {
fn eq(&self, other: &Self) -> bool {
self.as_ref() == other.as_ref()
}
}
impl Eq for Data {}
#[cfg(feature = "unstable-defmt")]
impl defmt::Format for Data {
fn format(&self, fmt: defmt::Formatter<'_>) {
self.as_ref().format(fmt)
}
}
macro_rules! data_from_array {
( $($len:literal),+ ) => {
$(
impl From<[u8; $len]> for Data {
#[inline]
fn from(arr: [u8; $len]) -> Self {
let mut bytes = [0; 8];
bytes[..$len].copy_from_slice(&arr);
Self {
len: $len,
bytes,
}
}
}
)+
};
}
data_from_array!(0, 1, 2, 3, 4, 5, 6, 7, 8);