Skip to content

Commit

Permalink
Merge pull request #42 from barafael/master
Browse files Browse the repository at this point in the history
Expose serde feature from serialport crate
  • Loading branch information
estokes authored Dec 31, 2024
2 parents c312358 + a9e9aed commit 5385318
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 61 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ description = "A serial port implementation for mio"
license = "MIT"
homepage = "https://github.com/berkowski/mio-serial"
repository = "https://github.com/berkowski/mio-serial"
documentation = "http://docs.rs/mio-serial"
documentation = "https://docs.rs/mio-serial"
readme = "README.md"
keywords = ["rs232", "serial", "mio"]
categories = ["asynchronous", "hardware-support"]
edition = "2018"
edition = "2021"

[package.metadata]
msrv = "1.70.0" # Used by cargo-msrv

[features]
default = []
libudev = ["serialport/libudev"]
serde = ["serialport/serde"]

[dependencies.mio]
version = "1"
Expand Down
22 changes: 11 additions & 11 deletions examples/read_serialport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
extern crate mio;
extern crate mio_serial;

use log::error;
use mio::{Events, Interest, Poll, Token};

use std::env;
Expand Down Expand Up @@ -32,7 +33,7 @@ pub fn main() -> io::Result<()> {
let mut events = Events::with_capacity(1);

// Create the serial port
println!("Opening {} at 9600,8N1", path);
println!("Opening {path} at 9600,8N1");
let mut rx = mio_serial::new(path, DEFAULT_BAUD).open_native_async()?;

// #[cfg(unix)]
Expand All @@ -55,28 +56,27 @@ pub fn main() -> io::Result<()> {
// Validate the token we registered our socket with,
// in this example it will only ever be one but we
// make sure it's valid none the less.
match event.token() {
SERIAL_TOKEN => loop {
if event.token() == SERIAL_TOKEN {
loop {
// In this loop we receive all packets queued for the socket.
match rx.read(&mut buf) {
Ok(count) => {
println!("{:?}", String::from_utf8_lossy(&buf[..count]))
println!("{:?}", String::from_utf8_lossy(&buf[..count]));
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
break;
}
Err(e) => {
println!("Quitting due to read error: {}", e);
println!("Quitting due to read error: {e}");
return Err(e);
}
}
},
_ => {
// This should never happen as we only registered our
// `UdpSocket` using the `UDP_SOCKET` token, but if it ever
// does we'll log it.
// warn!("Got event for unexpected token: {:?}", event);
}
} else {
// This should never happen as we only registered our
// `UdpSocket` using the `UDP_SOCKET` token, but if it ever
// does we'll log it.
error!("Got event for unexpected token: {:?}", event);
}
}
}
Expand Down
17 changes: 8 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pub use serialport::available_ports;
pub use serialport::new;

use mio::{event::Source, Interest, Registry, Token};
use std::convert::TryFrom;
use std::io::{Error as StdIoError, ErrorKind as StdIoErrorKind, Result as StdIoResult};
use std::time::Duration;

Expand Down Expand Up @@ -74,7 +73,7 @@ mod os_prelude {
}
use os_prelude::*;

/// SerialStream
/// A [`SerialStream`].
#[derive(Debug)]
pub struct SerialStream {
#[cfg(unix)]
Expand Down Expand Up @@ -500,7 +499,7 @@ impl crate::SerialPort for SerialStream {
Ok(Box::new(self.try_clone_native()?))
}

/// Cloning is not supported for SerialStream objects
/// Cloning is not supported for [`SerialStream`] objects
///
/// This logic has never really completely worked. Cloned file descriptors in asynchronous
/// code is a semantic minefield. Are you cloning the file descriptor? Are you cloning the
Expand All @@ -509,8 +508,8 @@ impl crate::SerialPort for SerialStream {
///
/// Maybe it can be done with more work, but until a clear use-case is required (or mio/tokio
/// gets an equivalent of the unix `AsyncFd` for async file handles, see
/// https://github.com/tokio-rs/tokio/issues/3781 and
/// https://github.com/tokio-rs/tokio/pull/3760#issuecomment-839854617) I would rather not
/// <https://github.com/tokio-rs/tokio/issues/3781> and
/// <https://github.com/tokio-rs/tokio/pull/3760#issuecomment-839854617>) I would rather not
/// have any code available over a kind-of-works-maybe impl. So I'll leave this code here
/// for now but hard-code it disabled.
fn try_clone(&self) -> crate::Result<Box<dyn crate::SerialPort>> {
Expand Down Expand Up @@ -674,7 +673,7 @@ mod io {
uninterruptibly!(match unsafe {
libc::write(
self.as_raw_fd(),
bytes.as_ptr() as *const libc::c_void,
bytes.as_ptr().cast::<libc::c_void>(),
bytes.len() as libc::size_t,
)
} {
Expand Down Expand Up @@ -887,13 +886,13 @@ impl Source for SerialStream {
}
}

/// An extension trait for SerialPortBuilder
/// An extension trait for [`SerialPortBuilder`]
///
/// This trait adds an additional method to SerialPortBuilder:
/// This trait adds an additional method to [`SerialPortBuilder`]:
///
/// - open_native_async
///
/// These methods mirror the `open_native` methods of SerialPortBuilder
/// These methods mirror the [`SerialPortBuilder::open_native`] methods
pub trait SerialPortBuilderExt {
/// Open a platform-specific interface to the port with the specified settings
fn open_native_async(self) -> Result<SerialStream>;
Expand Down
12 changes: 6 additions & 6 deletions tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ static LOGGING_INIT: Once = Once::new();

/// Default serial port names used for testing
#[cfg(unix)]
const DEFAULT_TEST_PORT_NAMES: &'static str = "USB0;USB1";
const DEFAULT_TEST_PORT_NAMES: &str = "USB0;USB1";

/// Default serial port names used for testing
#[cfg(windows)]
const DEFAULT_TEST_PORT_NAMES: &'static str = "COM1;COM2";
const DEFAULT_TEST_PORT_NAMES: &str = "COM1;COM2";

#[derive(Debug)]
pub struct Readiness(usize);
Expand All @@ -31,7 +31,7 @@ const READABLE: usize = 0b0000_0001;
const WRITABLE: usize = 0b0000_0010;
const AIO: usize = 0b0000_0100;
const LIO: usize = 0b0000_1000;
const ERROR: usize = 0b00010000;
const ERROR: usize = 0b0001_0000;
const READ_CLOSED: usize = 0b0010_0000;
const WRITE_CLOSED: usize = 0b0100_0000;
const PRIORITY: usize = 0b1000_0000;
Expand Down Expand Up @@ -92,6 +92,7 @@ impl From<Interest> for Readiness {
}
}

#[must_use]
pub fn init_with_poll() -> (Poll, Events) {
let poll = Poll::new().expect("unable to create poll object");
let events = Events::with_capacity(16);
Expand Down Expand Up @@ -148,16 +149,15 @@ pub fn expect_events(poll: &mut Poll, events: &mut Events, mut expected: Vec<Exp

assert!(
expected.is_empty(),
"the following expected events were not found: {:?}",
expected
"the following expected events were not found: {expected:?}",
);
}

pub fn assert_would_block(result: std::io::Result<usize>) {
match result {
Ok(_) => panic!("unexpected OK result, expected a `WouldBlock` error"),
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {}
Err(e) => panic!("unexpected error result: {}", e),
Err(e) => panic!("unexpected error result: {e}"),
}
}

Expand Down
57 changes: 24 additions & 33 deletions tests/test_serialstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn test_builder_open_async() {
.open_native_async()
.expect("unable to open serial port");

common::assert_baud_rate(&stream, baud_rate)
common::assert_baud_rate(&stream, baud_rate);
}

#[test]
Expand All @@ -28,12 +28,12 @@ fn test_native_from_blocking() {
let port = fixture.port_a;
let native_blocking = mio_serial::new(port, baud_rate)
.open_native()
.expect(format!("unable to open serial port {}", port).as_str());
.unwrap_or_else(|e| panic!("unable to open serial port {port}: {e}"));

let stream = mio_serial::SerialStream::try_from(native_blocking)
.expect("unable to convert from blocking serial port object");

common::assert_baud_rate(&stream, baud_rate)
common::assert_baud_rate(&stream, baud_rate);
}

#[test]
Expand All @@ -44,7 +44,7 @@ fn test_stream_open() {
let builder = mio_serial::new(port, baud_rate);
let stream = mio_serial::SerialStream::open(&builder).expect("unable to open serial port");

common::assert_baud_rate(&stream, baud_rate)
common::assert_baud_rate(&stream, baud_rate);
}

/// Port enumeration doesn't seem to work on virtual serial ports created by com0com during
Expand All @@ -54,55 +54,46 @@ fn test_stream_open() {
fn test_port_enumeration() {
let fixture = common::setup_virtual_serial_ports();
let ports = mio_serial::available_ports().expect("unable to enumerate serial ports");
for name in [fixture.port_a, fixture.port_b].iter() {
ports.iter().find(|&info| info.port_name == *name).expect(
format!(
"unable to find serial port named {} in enumerated ports",
name
)
.as_str(),
);
for name in [fixture.port_a, fixture.port_b] {
ports
.iter()
.find(|&info| info.port_name == *name)
.unwrap_or_else(|| {
panic!("unable to find serial port named {name} in enumerated ports")
});
}
}

#[test]
fn test_read_write_pair() {
let baud_rate = 38400;

const DATA1: &[u8] = b"Here is an example string";
const DATA2: &[u8] = b"And here is a reply to the example string";
const DEFAULT_BUF_SIZE: usize = 64;

let baud_rate = 38400;

let fixture = common::setup_virtual_serial_ports();
let (port_a, port_b) = (fixture.port_a, fixture.port_b);
let (mut poll, mut events) = common::init_with_poll();

let mut port_1 = mio_serial::new(port_a, baud_rate)
.open_native_async()
.expect(format!("unable to open serial port {}", port_a).as_str());
.unwrap_or_else(|e| panic!("unable to open serial port {port_a}: {e}"));
let mut port_2 = mio_serial::new(port_b, baud_rate)
.open_native_async()
.expect(format!("unable to open serial port {}", port_b).as_str());
.unwrap_or_else(|e| panic!("unable to open serial port {port_b}: {e}"));

// register both serial ports for read and write events
poll.registry()
.register(&mut port_1, TOKEN1, Interest::WRITABLE | Interest::READABLE)
.expect(
format!(
"unable to register port {} as readable and writable",
port_a
)
.as_str(),
);
.unwrap_or_else(|e| {
panic!("unable to register port {port_a} as readable and writable: {e}")
});
poll.registry()
.register(&mut port_2, TOKEN2, Interest::READABLE | Interest::WRITABLE)
.expect(
format!(
"unable to register port {} as readable and writable",
port_b
)
.as_str(),
);
.unwrap_or_else(|e| {
panic!("unable to register port {port_b} as readable and writable: {e}")
});

let mut buf = [0u8; DEFAULT_BUF_SIZE];

Expand All @@ -114,13 +105,13 @@ fn test_read_write_pair() {
);

// port2 should be blocking
common::assert_would_block(port_2.read(&mut buf).into());
common::assert_would_block(port_2.read(&mut buf));

// write data on port 1
common::checked_write(&mut port_1, DATA1);
port_1
.flush()
.expect(format!("unable to flush serial port {}", port_a).as_str());
.unwrap_or_else(|e| panic!("unable to flush serial port {port_a}: {e}"));

// port 2 should now be readable
common::expect_events(
Expand All @@ -142,7 +133,7 @@ fn test_read_write_pair() {
common::checked_write(&mut port_2, DATA2);
port_2
.flush()
.expect(format!("unable to flush serial port {}", port_b).as_str());
.unwrap_or_else(|e| panic!("unable to flush serial port {port_b}: {e}"));

// port 1 should now be readable
common::expect_events(
Expand Down

0 comments on commit 5385318

Please sign in to comment.