use derive_more::{Display, Error as DeriveError, From};
use socketcan::CANSocket;
use crate::{
events::{CanFrameError, Event, OneOrMany, ParseError},
frame::BadLen,
};
use OneOrMany::{Many, One};
#[derive(Debug, Display, DeriveError, From)]
pub enum Error {
ParseError(ParseError),
IoError(std::io::Error),
BadLen(BadLen),
}
impl From<CanFrameError> for Error {
fn from(value: CanFrameError) -> Self {
match value {
CanFrameError::BadLen(bl) => Error::BadLen(bl),
CanFrameError::ParseError(pe) => Error::ParseError(pe),
}
}
}
pub type Message = Result<Event, Error>;
pub struct Messages<'a> {
sock: &'a CANSocket,
pending: Vec<Event>,
}
impl<'a> Iterator for Messages<'a> {
type Item = Message;
fn next(&mut self) -> Option<Self::Item> {
if !self.pending.is_empty() {
return self.pending.pop().map(|event| Ok(event));
}
match self.sock.read_frame() {
Ok(frame) => match Event::parse(frame) {
Ok(Many(events)) => {
self.pending = events;
Some(Ok(self.pending.pop().unwrap()))
}
Ok(One(event)) => Some(Ok(event)),
Err(err) => Some(Err(err.into())),
},
Err(err) => match err.kind() {
std::io::ErrorKind::WouldBlock => None,
_ => Some(Err(Error::from(err))),
},
}
}
}
pub struct Listener {
sock: CANSocket,
}
impl Listener {
pub fn connect(
interface: &str,
blocking: bool,
) -> Result<Self, socketcan::CANSocketOpenError> {
let sock = CANSocket::open(interface)?;
sock.set_nonblocking(!blocking)?;
Ok(Listener { sock })
}
pub fn messages<'a>(&'a self) -> Messages<'a> {
Messages {
sock: &self.sock,
pending: Vec::new(),
}
}
}