Skip to content

Commit 21d1704

Browse files
committed
Deduplicate event reading code.
1 parent 139be3f commit 21d1704

File tree

2 files changed

+35
-53
lines changed

2 files changed

+35
-53
lines changed

Diff for: src/async_tokio.rs

+6-23
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@ use mio::{PollOpt, Ready, Token};
1717
use tokio::io::PollEvented;
1818

1919
use std::io;
20-
use std::mem;
2120
use std::os::unix::io::AsRawFd;
2221
use std::pin::Pin;
23-
use std::slice;
2422

2523
use super::errors::event_err;
26-
use super::{ffi, LineEvent, LineEventHandle, Result};
24+
use super::{LineEvent, LineEventHandle, Result};
2725

2826
struct PollWrapper {
2927
handle: LineEventHandle,
@@ -123,26 +121,11 @@ impl Stream for AsyncLineEventHandle {
123121
return Poll::Ready(Some(Err(e.into())));
124122
}
125123

126-
// TODO: This code should not be duplicated here.
127-
let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() };
128-
let mut data_as_buf = unsafe {
129-
slice::from_raw_parts_mut(
130-
&mut data as *mut ffi::gpioevent_data as *mut u8,
131-
mem::size_of::<ffi::gpioevent_data>(),
132-
)
133-
};
134-
match nix::unistd::read(
135-
self.evented.get_ref().handle.file.as_raw_fd(),
136-
&mut data_as_buf,
137-
) {
138-
Ok(bytes_read) => {
139-
if bytes_read != mem::size_of::<ffi::gpioevent_data>() {
140-
let e = nix::Error::Sys(nix::errno::Errno::EIO);
141-
Poll::Ready(Some(Err(event_err(e))))
142-
} else {
143-
Poll::Ready(Some(Ok(LineEvent(data))))
144-
}
145-
}
124+
match self.evented.get_ref().handle.read_event() {
125+
Ok(Some(event)) => Poll::Ready(Some(Ok(event))),
126+
Ok(None) => Poll::Ready(Some(Err(event_err(nix::Error::Sys(
127+
nix::errno::Errno::EIO,
128+
))))),
146129
Err(nix::Error::Sys(nix::errno::Errno::EAGAIN)) => {
147130
self.evented.clear_read_ready(cx, ready)?;
148131
Poll::Pending

Diff for: src/lib.rs

+29-30
Original file line numberDiff line numberDiff line change
@@ -950,21 +950,10 @@ impl LineEventHandle {
950950
/// kernel for the line which matches the subscription criteria
951951
/// specified in the `event_flags` when the handle was created.
952952
pub fn get_event(&self) -> Result<LineEvent> {
953-
let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() };
954-
let mut data_as_buf = unsafe {
955-
slice::from_raw_parts_mut(
956-
&mut data as *mut ffi::gpioevent_data as *mut u8,
957-
mem::size_of::<ffi::gpioevent_data>(),
958-
)
959-
};
960-
let bytes_read =
961-
nix::unistd::read(self.file.as_raw_fd(), &mut data_as_buf).map_err(event_err)?;
962-
963-
if bytes_read != mem::size_of::<ffi::gpioevent_data>() {
964-
let e = nix::Error::Sys(nix::errno::Errno::EIO);
965-
Err(event_err(e))
966-
} else {
967-
Ok(LineEvent(data))
953+
match self.read_event() {
954+
Ok(Some(event)) => Ok(event),
955+
Ok(None) => Err(event_err(nix::Error::Sys(nix::errno::Errno::EIO))),
956+
Err(e) => Err(event_err(e)),
968957
}
969958
}
970959

@@ -984,6 +973,28 @@ impl LineEventHandle {
984973
pub fn line(&self) -> &Line {
985974
&self.line
986975
}
976+
977+
/// Helper function which returns the line event if a complete event was read, Ok(None) if not
978+
/// enough data was read or the error returned by `read()`.
979+
///
980+
/// This function allows access to the raw `nix::Error` as required, for example, to theck
981+
/// whether read() returned -EAGAIN.
982+
pub(crate) fn read_event(&self) -> std::result::Result<Option<LineEvent>, nix::Error> {
983+
let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() };
984+
let mut data_as_buf = unsafe {
985+
slice::from_raw_parts_mut(
986+
&mut data as *mut ffi::gpioevent_data as *mut u8,
987+
mem::size_of::<ffi::gpioevent_data>(),
988+
)
989+
};
990+
let bytes_read = nix::unistd::read(self.file.as_raw_fd(), &mut data_as_buf)?;
991+
992+
if bytes_read != mem::size_of::<ffi::gpioevent_data>() {
993+
Ok(None)
994+
} else {
995+
Ok(Some(LineEvent(data)))
996+
}
997+
}
987998
}
988999

9891000
impl AsRawFd for LineEventHandle {
@@ -997,21 +1008,9 @@ impl Iterator for LineEventHandle {
9971008
type Item = Result<LineEvent>;
9981009

9991010
fn next(&mut self) -> Option<Result<LineEvent>> {
1000-
let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() };
1001-
let mut data_as_buf = unsafe {
1002-
slice::from_raw_parts_mut(
1003-
&mut data as *mut ffi::gpioevent_data as *mut u8,
1004-
mem::size_of::<ffi::gpioevent_data>(),
1005-
)
1006-
};
1007-
match nix::unistd::read(self.file.as_raw_fd(), &mut data_as_buf) {
1008-
Ok(bytes_read) => {
1009-
if bytes_read != mem::size_of::<ffi::gpioevent_data>() {
1010-
None
1011-
} else {
1012-
Some(Ok(LineEvent(data)))
1013-
}
1014-
}
1011+
match self.read_event() {
1012+
Ok(None) => None,
1013+
Ok(Some(event)) => Some(Ok(event)),
10151014
Err(e) => Some(Err(event_err(e))),
10161015
}
10171016
}

0 commit comments

Comments
 (0)