Skip to content

Commit

Permalink
embedded: Implement both blocking and non-blocking traits
Browse files Browse the repository at this point in the history
  • Loading branch information
dbrgn committed Nov 13, 2022
1 parent 32031cb commit 27eabae
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 31 deletions.
13 changes: 8 additions & 5 deletions examples/embedded_hal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@
//! instance can be passed to functions / drivers that expect a type that
//! implements the embedded-hal traits.

use embedded_hal_nb::serial;
fn take_nonblocking_reader<R: embedded_hal_nb::serial::Read<u8>>(_r: &R) {
// do nothing, but things should typecheck
}

fn take_reader<R: serial::Read<u8>>(_r: &R) {
fn take_nonblocking_writer<W: embedded_hal_nb::serial::Write<u8>>(_w: &W) {
// do nothing, but things should typecheck
}

fn take_writer<W: serial::Write<u8>>(_w: &W) {
fn take_blocking_writer<W: embedded_hal::serial::Write<u8>>(_w: &W) {
// do nothing, but things should typecheck
}

fn main() {
let port = serialport::new("/dev/null", 9600)
.open()
.expect("This example isn't meant for running. It just demonstrates compatibility with embedded-hal on a type level.");
take_reader(&port);
take_writer(&port);
take_nonblocking_reader(&port);
take_nonblocking_writer(&port);
take_blocking_writer(&port);
}
80 changes: 54 additions & 26 deletions src/embedded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use std::io;

use embedded_hal_nb::serial;
use embedded_hal::serial::{ErrorType, ErrorKind};

use crate::SerialPort;

Expand All @@ -13,47 +13,75 @@ pub struct SerialError {
kind: io::ErrorKind,
}

// Implement `serial::Error` for SerialError
impl serial::Error for SerialError {
fn kind(&self) -> serial::ErrorKind {
impl embedded_hal::serial::Error for SerialError {
fn kind(&self) -> ErrorKind {
#[allow(clippy::match_single_binding)]
match self.kind {
_other => serial::ErrorKind::Other,
_ => ErrorKind::Other,
}
}
}

fn io_error_to_nb(err: io::Error) -> nb::Error<SerialError> {
match err.kind() {
io::ErrorKind::WouldBlock | io::ErrorKind::Interrupted => nb::Error::WouldBlock,
other => nb::Error::Other(SerialError { kind: other }),
impl From<io::Error> for SerialError {
fn from(e: io::Error) -> Self {
SerialError {
kind: e.kind(),
}
}
}

impl serial::ErrorType for Box<dyn SerialPort> {
impl ErrorType for Box<dyn SerialPort> {
type Error = SerialError;
}

impl serial::Read<u8> for Box<dyn SerialPort> {
fn read(&mut self) -> nb::Result<u8, Self::Error> {
let mut buffer = [0; 1];
let bytes_read = io::Read::read(self, &mut buffer).map_err(io_error_to_nb)?;
if bytes_read > 0 {
Ok(buffer[0])
} else {
Err(nb::Error::WouldBlock)

mod nonblocking {
use super::*;
use embedded_hal_nb::serial;

fn io_error_to_nb(err: io::Error) -> nb::Error<SerialError> {
match err.kind() {
io::ErrorKind::WouldBlock | io::ErrorKind::Interrupted => nb::Error::WouldBlock,
other => nb::Error::Other(SerialError { kind: other }),
}
}
}

impl serial::Write<u8> for Box<dyn SerialPort> {
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
io::Write::write(self, &[word])
.map_err(io_error_to_nb)
.map(|_| ())
impl serial::Read<u8> for Box<dyn SerialPort> {
fn read(&mut self) -> nb::Result<u8, Self::Error> {
let mut buffer = [0; 1];
let bytes_read = io::Read::read(self, &mut buffer).map_err(io_error_to_nb)?;
if bytes_read > 0 {
Ok(buffer[0])
} else {
Err(nb::Error::WouldBlock)
}
}
}

fn flush(&mut self) -> nb::Result<(), Self::Error> {
io::Write::flush(self).map_err(io_error_to_nb)
impl serial::Write<u8> for Box<dyn SerialPort> {
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
io::Write::write(self, &[word])
.map_err(io_error_to_nb)
.map(|_| ())
}

fn flush(&mut self) -> nb::Result<(), Self::Error> {
io::Write::flush(self).map_err(io_error_to_nb)
}
}
}

mod blocking {
use super::*;
use embedded_hal::serial;

impl serial::Write<u8> for Box<dyn SerialPort> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
Ok(io::Write::write_all(self, buffer)?)
}

fn flush(&mut self) -> Result<(), Self::Error> {
Ok(io::Write::flush(self)?)
}
}
}

0 comments on commit 27eabae

Please sign in to comment.