genio 0.2.1

A type safe, low level replacement for `std::io`. Supports `no_std` for embedded development, just disable cargo feature `std`. Because of limitations of `std::io::Error` type, `genio` provides `Read` and `Write` traits that allow implementors to choose their own type. This type can be better at expressing what kinds of error can happen.
Documentation
use Read;
use Write;
use error::{IntrError, IntoIntrError};

/// Restarts all interrupted operations.
///
/// All Read and Write operations that might fail with error indicating interruption (like EINTR)
/// will be restarted when wrapped in this type.
///
/// The error types indicate that interrupted error case has been handled.
pub struct Restarting<T> (T);

impl<T> Restarting<T> {
    /// Creates restarting IO.
    pub fn new(io: T) -> Self {
        Restarting(io)
    }

    /// Converts to lower-level reader.
    pub fn into_inner(self) -> T {
        self.0
    }

    fn restart_call<S, E: IntoIntrError, F: FnMut() -> Result<S, E>>(mut f: F) -> Result<S, E::NonIntr> {
        loop {
            match f().map_err(IntoIntrError::into_intr_error) {
                Ok(success) => return Ok(success),
                Err(IntrError::Other(e)) => return Err(e),
                Err(IntrError::Interrupted) => (),
            }
        }
    }
}

impl<R> Read for Restarting<R> where R: Read, R::ReadError: IntoIntrError {
    type ReadError = <<R as Read>::ReadError as IntoIntrError>::NonIntr;

    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError> {
        Self::restart_call(|| self.0.read(buf))    
    }
}

impl<W> Write for Restarting<W> where W: Write, W::WriteError: IntoIntrError, W::FlushError: IntoIntrError {
    type WriteError = <<W as Write>::WriteError as IntoIntrError>::NonIntr;
    type FlushError = <<W as Write>::FlushError as IntoIntrError>::NonIntr;

    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
        Self::restart_call(|| self.0.write(buf))    
    }

    fn flush(&mut self) -> Result<(), Self::FlushError> {
        Self::restart_call(|| self.0.flush())    
    }

    fn size_hint(&mut self, bytes: usize) {
        self.0.size_hint(bytes);
    }

    fn uses_size_hint(&self) -> bool {
        self.0.uses_size_hint()
    }
}