use alloc::boxed::Box;
use alloc::vec::Vec;
use core::cell::Cell;
use core::fmt::Debug;
use sealed::sealed;
use crate::{Error, scheduling};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Event {
Read,
Write,
}
#[sealed(pub(crate))]
pub trait Serial {
fn read(&self, buffer: &mut [u8]) -> Result<usize, Error>;
fn write(&self, buffer: &[u8]) -> Result<usize, Error>;
fn flush(&self) -> Result<(), Error>;
unsafe fn register(
&self, event: Event, func: extern "C" fn(*const u8), data: *const u8,
) -> Result<(), Error>;
fn unregister(&self, event: Event) -> Result<(), Error>;
}
pub fn read<T: Serial>(serial: &T, buffer: &mut [u8]) -> Result<usize, Error> {
serial.read(buffer)
}
pub fn read_any<T: Serial>(serial: &T, buffer: &mut [u8]) -> Result<usize, Error> {
let mut reader = Reader::new(serial, buffer);
scheduling::wait_until(|| !reader.is_empty());
reader.result()
}
pub fn read_all<T: Serial>(serial: &T, buffer: &mut [u8]) -> Result<(), Error> {
let mut reader = Reader::new(serial, buffer);
scheduling::wait_until(|| reader.is_done());
reader.result()?;
Ok(())
}
pub fn read_byte<T: Serial>(serial: &T) -> Result<u8, Error> {
let mut byte = 0;
read_any(serial, core::slice::from_mut(&mut byte))?;
Ok(byte)
}
pub fn write<T: Serial>(serial: &T, buffer: &[u8]) -> Result<usize, Error> {
serial.write(buffer)
}
pub fn write_any<T: Serial>(serial: &T, buffer: &[u8]) -> Result<usize, Error> {
let mut writer = Writer::new(serial, buffer);
scheduling::wait_until(|| !writer.is_empty());
writer.result()
}
pub fn write_all<T: Serial>(serial: &T, buffer: &[u8]) -> Result<(), Error> {
let mut writer = Writer::new(serial, buffer);
scheduling::wait_until(|| writer.is_done());
writer.result()?;
Ok(())
}
pub fn flush<T: Serial>(serial: &T) -> Result<(), Error> {
serial.flush()
}
pub struct Listener<'a, T: Serial> {
serial: &'a T,
event: Event,
notified: *const Cell<bool>,
}
impl<'a, T: Serial> Listener<'a, T> {
pub fn new(serial: &'a T, event: Event) -> Self {
let notified = Box::into_raw(Box::new(Cell::new(true)));
let func = Self::call;
let data = notified as *const u8;
unsafe { serial.register(event, func, data) }.unwrap();
Listener { serial, event, notified }
}
pub fn is_notified(&mut self) -> bool {
unsafe { &*self.notified }.replace(false)
}
extern "C" fn call(data: *const u8) {
let notified = unsafe { &*(data as *const Cell<bool>) };
notified.set(true);
}
}
impl<T: Serial> Drop for Listener<'_, T> {
fn drop(&mut self) {
self.serial.unregister(self.event).unwrap();
drop(unsafe { Box::from_raw(self.notified as *mut Cell<bool>) });
}
}
pub struct DelimitedReader<'a, T: Serial> {
listener: Listener<'a, T>,
buffer: Vec<u8>,
frame: Option<usize>, delimiter: u8,
}
impl<'a, T: Serial> DelimitedReader<'a, T> {
pub fn new(serial: &'a T, delimiter: u8) -> Self {
let listener = Listener::new(serial, Event::Read);
DelimitedReader { listener, buffer: Vec::new(), frame: None, delimiter }
}
pub fn next_frame(&mut self) -> Option<Vec<u8>> {
if self.frame.is_none() && self.listener.is_notified() {
self.flush();
}
self.frame.map(|len| {
let mut frame = self.buffer.split_off(len + 1);
core::mem::swap(&mut frame, &mut self.buffer);
self.frame = self.buffer.iter().position(|&x| x == self.delimiter);
frame
})
}
pub fn stop(self) -> Vec<u8> {
self.buffer
}
fn flush(&mut self) {
while self.read() {}
}
fn read(&mut self) -> bool {
let mut data = [0; 32];
let len = self.listener.serial.read(&mut data).unwrap();
let pos = self.buffer.len();
self.buffer.extend_from_slice(&data[.. len]);
if self.frame.is_none() {
for i in pos .. pos + len {
if self.buffer[i] == self.delimiter {
self.frame = Some(i);
break;
}
}
}
len == data.len()
}
}
#[must_use]
pub struct Reader<'a, T: Serial>(Updater<'a, T>);
impl<'a, T: Serial> Reader<'a, T> {
pub fn new(serial: &'a T, buffer: &'a mut [u8]) -> Self {
Reader(Updater::new(serial, Kind::Reader { buffer }))
}
pub fn is_empty(&mut self) -> bool {
self.0.is_empty()
}
pub fn is_done(&mut self) -> bool {
self.0.is_done()
}
pub fn result(self) -> Result<usize, Error> {
self.0.result()
}
}
#[must_use]
pub struct Writer<'a, T: Serial>(Updater<'a, T>);
impl<'a, T: Serial> Writer<'a, T> {
pub fn new(serial: &'a T, buffer: &'a [u8]) -> Self {
Writer(Updater::new(serial, Kind::Writer { buffer }))
}
pub fn is_empty(&mut self) -> bool {
self.0.is_empty()
}
pub fn is_done(&mut self) -> bool {
self.0.is_done()
}
pub fn result(self) -> Result<usize, Error> {
self.0.result()
}
}
struct Updater<'a, T: Serial> {
listener: Option<Listener<'a, T>>,
kind: Kind<'a>,
result: Result<usize, Error>,
}
impl<'a, T: Serial> Updater<'a, T> {
fn new(serial: &'a T, kind: Kind<'a>) -> Self {
let event = kind.event();
let mut result = Updater { listener: None, kind, result: Ok(0) };
if result.should_listen() {
result.listener = Some(Listener::new(serial, event));
}
let _ = result.update();
result
}
fn is_empty(&mut self) -> bool {
matches!(self.update(), Ok(0))
}
fn is_done(&mut self) -> bool {
let _ = self.update();
self.listener.is_none()
}
fn result(mut self) -> Result<usize, Error> {
self.update()
}
fn update(&mut self) -> Result<usize, Error> {
let listener = match &mut self.listener {
Some(x) => x,
None => return self.result,
};
if !listener.is_notified() {
return self.result;
}
let pos = self.result.as_mut().unwrap();
match self.kind.update(listener.serial, *pos) {
Ok(len) => *pos += len,
err => self.result = err,
}
if !self.should_listen() {
self.listener = None;
}
self.result
}
fn should_listen(&self) -> bool {
matches!(self.result, Ok(len) if len < self.kind.len())
}
}
enum Kind<'a> {
Reader { buffer: &'a mut [u8] },
Writer { buffer: &'a [u8] },
}
impl Kind<'_> {
fn event(&self) -> Event {
match self {
Kind::Reader { .. } => Event::Read,
Kind::Writer { .. } => Event::Write,
}
}
fn len(&self) -> usize {
match self {
Kind::Reader { buffer } => buffer.len(),
Kind::Writer { buffer } => buffer.len(),
}
}
fn update(&mut self, serial: &impl Serial, pos: usize) -> Result<usize, Error> {
match self {
Kind::Reader { buffer } => serial.read(&mut buffer[pos ..]),
Kind::Writer { buffer } => serial.write(&buffer[pos ..]),
}
}
}