use derive_more::{Display, From};
use static_assertions as sa;
use crate::Frame;
mod parse_error;
pub use parse_error::ParseError;
pub mod battery;
pub mod bus;
pub mod camera;
pub mod control_panel;
pub mod datetime;
pub mod doors;
pub mod engine;
pub mod force;
pub mod hvac;
pub mod ignition;
pub mod lights;
pub mod locks;
pub mod odometer;
pub mod remote;
pub mod steering_wheel;
use FrontOrRear::{Front, Rear};
use OneOrMany::{Many, One};
sa::const_assert_eq!(std::mem::size_of::<Event>(), 16);
sa::const_assert_eq!(std::mem::align_of::<Event>(), 8);
sa::const_assert_eq!(std::mem::size_of::<control_panel::ControlPanel>(), 16);
sa::const_assert_eq!(std::mem::align_of::<control_panel::ControlPanel>(), 8);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Debug, Display, From, Clone)]
pub enum Event {
Battery(battery::Battery),
Remote(remote::Remote),
Ignition(ignition::Ignition),
SteeringWheel(steering_wheel::Buttons),
ControlPanel(control_panel::ControlPanel),
Lights(lights::Lights),
Doors(doors::Doors),
Locks(locks::Locks),
Force(force::Force),
Camera(camera::Camera),
Engine(engine::Engine),
HVAC(hvac::HVAC),
DateTime(datetime::DateTime),
Odometer(odometer::Odometer),
Bus(bus::Bus),
}
impl Event {
#[inline(always)] pub fn parse<I, E>(input: I) -> Result<OneOrMany<Event>, E>
where
I: TryInto<OneOrMany<Event>, Error = E>,
{
input.try_into()
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Debug, Display, Clone)]
pub enum OneOrMany<T> {
One(T),
Many(Vec<T>),
}
impl<T> IntoIterator for OneOrMany<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter(Some(self))
}
}
pub struct IntoIter<T>(Option<OneOrMany<T>>);
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let (elem, next) = match self.0.take() {
Some(oom) => match oom {
One(elem) => (Some(elem), None),
Many(mut vec) => (vec.pop(), Some(Many(vec))),
},
None => (None, None),
};
self.0 = next;
elem
}
}
impl TryFrom<Frame> for OneOrMany<Event> {
type Error = ParseError;
fn try_from(frame: Frame) -> Result<Self, Self::Error> {
match frame.id() {
0x2c2 => Ok(One(Event::Battery(frame.try_into()?))),
0x1c0 => Ok(One(Event::Remote(frame.try_into()?))),
0x122 => Ok(One(Event::Ignition(frame.try_into()?))),
0x318 => Ok(One(Event::SteeringWheel(frame.try_into()?))),
0x2d3 | 0x2d4 | 0x273 => {
Ok(One(Event::ControlPanel(frame.try_into()?)))
}
0x2fa => {
const LEN: usize = 8;
let mut events = Vec::new();
let mut errors = Vec::new();
let data: [u8; LEN] = match frame.data().try_into() {
Ok(data) => data,
Err(_) => {
return Err(ParseError::Len {
frame,
expected: LEN,
})
}
};
let doors = doors::Doors::from_bits(data[0]).unwrap();
events.push(Event::Doors(doors));
match lights::ParkingLights::try_from(frame.clone()) {
Ok(parking_lights) => events.push(Event::Lights(
lights::Lights::ParkingLights(parking_lights),
)),
Err(parse_error) => errors.push(parse_error),
};
match lights::Dimmer::try_from(frame.clone()) {
Ok(dimmer) => events
.push(Event::Lights(lights::Lights::Dimmer(dimmer))),
Err(parse_error) => errors.push(parse_error),
};
let locks = locks::Locks::from_bits(frame.data()[3]).unwrap();
events.push(Event::Locks(locks));
if errors.is_empty() {
Ok(Many(events))
} else {
Err(ParseError::Data {
frame,
detail: format!("There were error(s) parsing a frame from `0x2fa`: {errors:?}"),
})
}
}
0x24e | 0x252 => Ok(One(Event::Force(frame.try_into()?))),
0x302 => Ok(One(Event::Camera(frame.try_into()?))),
0x322 | 0x340 => {
Ok(OneOrMany::<engine::Engine>::try_from(frame)?.into())
}
0x33a => Ok(One(Event::HVAC(frame.try_into()?))),
0x350 => Ok(One(Event::DateTime(frame.try_into()?))),
0x3d2 => Ok(One(Event::Odometer(frame.try_into()?))),
0x401 => Ok(One(Event::Bus(frame.try_into()?))),
_ => Err(ParseError::Id { frame }),
}
}
}
#[cfg(feature = "socketcan")]
impl TryFrom<socketcan::CANFrame> for OneOrMany<Event> {
type Error = CanFrameError;
fn try_from(frame: socketcan::CANFrame) -> Result<Self, Self::Error> {
let frame = Frame::from_socketcan(frame)?;
frame.try_into().map_err(|pe| CanFrameError::ParseError(pe))
}
}
impl TryFrom<libc::can_frame> for OneOrMany<Event> {
type Error = CanFrameError;
fn try_from(frame: libc::can_frame) -> Result<Self, Self::Error> {
let frame = Frame::from_libc_can_frame(frame)?;
frame.try_into().map_err(|pe| CanFrameError::ParseError(pe))
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Debug, Display, Clone)]
pub enum FrontOrRear<T> {
Front(T),
Rear(T),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(
Debug, derive_more::Error, derive_more::From, derive_more::Display,
)]
pub enum CanFrameError {
BadLen(crate::frame::BadLen),
ParseError(ParseError),
}