From 21d1704319fd747f67276149afbd7a285700de20 Mon Sep 17 00:00:00 2001 From: Mathias Gottschlag Date: Thu, 14 May 2020 09:06:21 +0200 Subject: [PATCH] Deduplicate event reading code. --- src/async_tokio.rs | 29 +++++------------------ src/lib.rs | 59 +++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 53 deletions(-) diff --git a/src/async_tokio.rs b/src/async_tokio.rs index 8f8d873..3c439fb 100644 --- a/src/async_tokio.rs +++ b/src/async_tokio.rs @@ -17,13 +17,11 @@ use mio::{PollOpt, Ready, Token}; use tokio::io::PollEvented; use std::io; -use std::mem; use std::os::unix::io::AsRawFd; use std::pin::Pin; -use std::slice; use super::errors::event_err; -use super::{ffi, LineEvent, LineEventHandle, Result}; +use super::{LineEvent, LineEventHandle, Result}; struct PollWrapper { handle: LineEventHandle, @@ -123,26 +121,11 @@ impl Stream for AsyncLineEventHandle { return Poll::Ready(Some(Err(e.into()))); } - // TODO: This code should not be duplicated here. - let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() }; - let mut data_as_buf = unsafe { - slice::from_raw_parts_mut( - &mut data as *mut ffi::gpioevent_data as *mut u8, - mem::size_of::(), - ) - }; - match nix::unistd::read( - self.evented.get_ref().handle.file.as_raw_fd(), - &mut data_as_buf, - ) { - Ok(bytes_read) => { - if bytes_read != mem::size_of::() { - let e = nix::Error::Sys(nix::errno::Errno::EIO); - Poll::Ready(Some(Err(event_err(e)))) - } else { - Poll::Ready(Some(Ok(LineEvent(data)))) - } - } + match self.evented.get_ref().handle.read_event() { + Ok(Some(event)) => Poll::Ready(Some(Ok(event))), + Ok(None) => Poll::Ready(Some(Err(event_err(nix::Error::Sys( + nix::errno::Errno::EIO, + ))))), Err(nix::Error::Sys(nix::errno::Errno::EAGAIN)) => { self.evented.clear_read_ready(cx, ready)?; Poll::Pending diff --git a/src/lib.rs b/src/lib.rs index d91f53f..0fc6f7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -950,21 +950,10 @@ impl LineEventHandle { /// kernel for the line which matches the subscription criteria /// specified in the `event_flags` when the handle was created. pub fn get_event(&self) -> Result { - let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() }; - let mut data_as_buf = unsafe { - slice::from_raw_parts_mut( - &mut data as *mut ffi::gpioevent_data as *mut u8, - mem::size_of::(), - ) - }; - let bytes_read = - nix::unistd::read(self.file.as_raw_fd(), &mut data_as_buf).map_err(event_err)?; - - if bytes_read != mem::size_of::() { - let e = nix::Error::Sys(nix::errno::Errno::EIO); - Err(event_err(e)) - } else { - Ok(LineEvent(data)) + match self.read_event() { + Ok(Some(event)) => Ok(event), + Ok(None) => Err(event_err(nix::Error::Sys(nix::errno::Errno::EIO))), + Err(e) => Err(event_err(e)), } } @@ -984,6 +973,28 @@ impl LineEventHandle { pub fn line(&self) -> &Line { &self.line } + + /// Helper function which returns the line event if a complete event was read, Ok(None) if not + /// enough data was read or the error returned by `read()`. + /// + /// This function allows access to the raw `nix::Error` as required, for example, to theck + /// whether read() returned -EAGAIN. + pub(crate) fn read_event(&self) -> std::result::Result, nix::Error> { + let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() }; + let mut data_as_buf = unsafe { + slice::from_raw_parts_mut( + &mut data as *mut ffi::gpioevent_data as *mut u8, + mem::size_of::(), + ) + }; + let bytes_read = nix::unistd::read(self.file.as_raw_fd(), &mut data_as_buf)?; + + if bytes_read != mem::size_of::() { + Ok(None) + } else { + Ok(Some(LineEvent(data))) + } + } } impl AsRawFd for LineEventHandle { @@ -997,21 +1008,9 @@ impl Iterator for LineEventHandle { type Item = Result; fn next(&mut self) -> Option> { - let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() }; - let mut data_as_buf = unsafe { - slice::from_raw_parts_mut( - &mut data as *mut ffi::gpioevent_data as *mut u8, - mem::size_of::(), - ) - }; - match nix::unistd::read(self.file.as_raw_fd(), &mut data_as_buf) { - Ok(bytes_read) => { - if bytes_read != mem::size_of::() { - None - } else { - Some(Ok(LineEvent(data))) - } - } + match self.read_event() { + Ok(None) => None, + Ok(Some(event)) => Some(Ok(event)), Err(e) => Some(Err(event_err(e))), } }