From 75b69de3b4b8e18c175064cfd21a224cbc0b956a Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Wed, 7 Mar 2018 16:36:12 +0100 Subject: [PATCH] Add basic io::{Read, Write} traits modeled after futures-io --- src/io/mod.rs | 5 ++++ src/io/read.rs | 43 +++++++++++++++++++++++++++++ src/io/write.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 ++++ 4 files changed, 126 insertions(+) create mode 100644 src/io/mod.rs create mode 100644 src/io/read.rs create mode 100644 src/io/write.rs diff --git a/src/io/mod.rs b/src/io/mod.rs new file mode 100644 index 0000000..a557f9a --- /dev/null +++ b/src/io/mod.rs @@ -0,0 +1,5 @@ +mod read; +mod write; + +pub use self::read::Read; +pub use self::write::Write; diff --git a/src/io/read.rs b/src/io/read.rs new file mode 100644 index 0000000..1cb275e --- /dev/null +++ b/src/io/read.rs @@ -0,0 +1,43 @@ +use core::cmp; + +use Result; + +/// Non-blocking reader trait +pub trait Read { + /// An enumeration of possible errors + /// + /// May be `!` (`never_type`) for infallible implementations + type Error; + + /// Pull some bytes from this source into the specified buffer, returning how many bytes were + /// read. + /// + /// If an object needs to block for a read it will return an `Err(nb::Error::WouldBlock)` + /// return value. + /// + /// If the return value of this method is `Ok(n)`, then it must be guaranteed that `0 <= n <= + /// buf.len()`. The `n` value indicates that the buffer `buf` has been filled in with `n` bytes + /// of data from this source. If `n == 0 && buf.len() > 0` then it can be assumed that this + /// reader has run out of data and will not be able service any future read calls. + fn read(&mut self, buf: &mut [u8]) -> Result; +} + +impl<'a, R: ?Sized + Read> Read for &'a mut R { + type Error = R::Error; + + fn read(&mut self, buf: &mut [u8]) -> Result { + (**self).read(buf) + } +} + +impl<'a> Read for &'a [u8] { + type Error = !; + + fn read(&mut self, buf: &mut [u8]) -> Result { + let len = cmp::min(self.len(), buf.len()); + let (head, tail) = self.split_at(len); + buf[..len].copy_from_slice(head); + *self = tail; + Ok(len) + } +} diff --git a/src/io/write.rs b/src/io/write.rs new file mode 100644 index 0000000..e516a85 --- /dev/null +++ b/src/io/write.rs @@ -0,0 +1,73 @@ +use core::{cmp, mem}; + +use Result; + +/// Non-blocking writer trait +pub trait Write { + /// An enumeration of possible errors + /// + /// May be `!` (`never_type`) for infallible implementations + type Error; + + /// Push some bytes into this source from the specified buffer, returning how many bytes were + /// written. + /// + /// If an object needs to block for a write it will return an `Err(nb::Error::WouldBlock)` + /// return value. + /// + /// If the return value of this method is `Ok(n)`, then it must be guaranteed that `0 <= n <= + /// buf.len()`. The `n` value indicates that `n` bytes from the buffer `buf` have been written + /// to this source. If `n == 0 && buf.len() > 0` then it can be assumed that this writer has + /// run out of space and will not be able to service future writes. + fn write(&mut self, buf: &[u8]) -> Result; + + /// Attempt to flush the object, ensuring that any buffered data reach their destination. + /// + /// On success, returns `Ok(())`. + /// + /// If flushing cannot immediately complete, this method returns `Err(nb::Error::WouldBlock)`. + fn flush(&mut self) -> Result<(), Self::Error>; + + /// Attempt to close the object. + /// + /// On success, returns `Ok(())`. + /// + /// If closing cannot immediately complete, this method returns `Err(nb::Error::WouldBlock)`. + fn close(&mut self) -> Result<(), Self::Error>; +} + +impl<'a, W: ?Sized + Write> Write for &'a mut W { + type Error = W::Error; + + fn write(&mut self, buf: &[u8]) -> Result { + (**self).write(buf) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + (**self).flush() + } + + fn close(&mut self) -> Result<(), Self::Error> { + (**self).close() + } +} + +impl<'a> Write for &'a mut [u8] { + type Error = !; + + fn write(&mut self, buf: &[u8]) -> Result { + let len = cmp::min(self.len(), buf.len()); + let (head, tail) = mem::replace(self, &mut []).split_at_mut(len); + head.copy_from_slice(&buf[..len]); + *self = tail; + Ok(len) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + + fn close(&mut self) -> Result<(), Self::Error> { + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 7f0d386..70447ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -357,6 +357,11 @@ #![no_std] #![deny(warnings)] +#![cfg_attr(feature = "unstable", feature(never_type))] + +#[cfg(feature = "unstable")] +pub mod io; + use core::fmt; /// A non-blocking result