use super::*;
pub trait AnyMessage: super::AnyMessage {
fn new(m: MessageBuilder) -> Result<Self, TooMuchData>;
}
impl<const N: usize> super::AnyMessage for Message<N>
where
RawMessage<N>: super::AnyMessage,
{
const REG: u8 = RawMessage::<N>::REG;
}
impl<const N: usize> Raw for Message<N> {
fn id(&self) -> Id {
self.0.id()
}
fn decoded_dlc(&self) -> usize {
self.0.decoded_dlc()
}
fn dlc(&self) -> u8 {
self.0.dlc()
}
fn fd_format(&self) -> bool {
self.0.fd_format()
}
fn is_remote_frame(&self) -> bool {
self.0.is_remote_frame()
}
fn data(&self) -> &[u8] {
self.0.data()
}
fn is_extended(&self) -> bool {
self.0.is_extended()
}
fn is_transmitter_error_passive(&self) -> bool {
self.0.is_transmitter_error_passive()
}
fn bit_rate_switching(&self) -> bool {
self.0.bit_rate_switching()
}
}
impl<const N: usize> AnyMessage for Message<N>
where
Message<N>: super::AnyMessage,
{
fn new(m: MessageBuilder) -> Result<Self, TooMuchData> {
m.build()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug)]
pub struct Message<const N: usize>(pub(super) RawMessage<N>);
pub enum ClassicFrameType<'a> {
Data(&'a [u8]),
Remote {
desired_len: usize,
},
}
pub enum FrameType<'a> {
Classic(ClassicFrameType<'a>),
FlexibleDatarate {
payload: &'a [u8],
bit_rate_switching: bool,
force_error_state_indicator: bool,
},
}
pub struct MessageBuilder<'a> {
pub id: Id,
pub frame_type: FrameType<'a>,
pub store_tx_event: Option<u8>,
}
impl MessageBuilder<'_> {
pub fn build<const N: usize>(self) -> Result<Message<N>, TooMuchData> {
let mut data = [0; N];
let mut copy_payload = |d: &[u8]| {
if d.len() > N {
return Err(TooMuchData);
}
data[..d.len()].copy_from_slice(d);
Ok(())
};
let id_field = match self.id {
Id::Standard(id) => (id.as_raw() as u32) << 18,
Id::Extended(id) => id.as_raw(),
};
let xtd = matches!(self.id, Id::Extended(_));
let (fdf, brs, esi, rtr, len) = match self.frame_type {
FrameType::Classic(payload) => {
let (rtr, len) = match payload {
ClassicFrameType::Data(payload) => {
copy_payload(payload)?;
(false, payload.len())
}
ClassicFrameType::Remote { desired_len } => (true, desired_len),
};
(false, false, false, rtr, len)
}
FrameType::FlexibleDatarate {
payload,
bit_rate_switching: brs,
force_error_state_indicator: esi,
} => {
copy_payload(payload)?;
(true, brs, esi, false, payload.len())
}
};
let dlc = len_to_dlc(len, fdf)?;
let efc = self.store_tx_event.is_some();
let mm = self.store_tx_event.unwrap_or(0);
let t0 = id_field | (rtr as u32) << 29 | (xtd as u32) << 30 | (esi as u32) << 31;
let t1 = (((dlc & 0xf) as u32) << 16)
| ((brs as u32) << 20)
| ((fdf as u32) << 21)
| ((efc as u32) << 23)
| ((mm as u32) << 24);
Ok(Message(RawMessage {
header: [t0, t1],
data,
}))
}
}