Reorganize std::io facade

This commit is contained in:
Igor Matuszewski 2020-01-20 19:34:47 +01:00
parent 9ecf91504a
commit 15bfaf6a07
3 changed files with 59 additions and 17 deletions

View File

@ -1,15 +1,33 @@
//! A tiny, `no_std`-friendly facade around `std::io`.
//! Reexports types from `std` when available; otherwise reimplements and
//! provides some of the core logic.
//!
//! The main reason that `std::io` hasn't found itself reexported as part of
//! the `core` crate is the `std::io::{Read, Write}` traits' reliance on
//! `std::io::Error`, which may contain internally a heap-allocated `Box<Error>`
//! and/or now relying on OS-specific `std::backtrace::Backtrace`.
//!
//! Because of this, we simply redefine those traits as if the error type is
//! simply a `&'static str` and reimplement those traits for `core` primitives
//! or `alloc` types, e.g. `Vec<T>`.
#[cfg(not(feature = "std"))]
use core::slice;
use lib::*;
#[cfg(feature = "std")]
pub use std::io::{Result, Write, Read, Error, Bytes, ErrorKind};
pub use std::io::ErrorKind;
#[cfg(feature = "std")]
pub use std::io::Error;
#[cfg(not(feature = "std"))]
pub type Error = &'static str;
#[cfg(feature = "std")]
pub use std::io::Result;
#[cfg(not(feature = "std"))]
pub type Result<T> = core::result::Result<T, Error>;
#[cfg(feature = "std")]
pub use std::io::Write;
#[cfg(not(feature = "std"))]
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;
@ -30,35 +48,57 @@ pub trait Write {
#[cfg(not(feature = "std"))]
impl<W: Write> Write for &mut W {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
(*self).write(buf)
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
(*self).write_all(buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
(*self).flush()
}
}
#[cfg(all(not(feature = "std"), feature = "alloc"))]
impl Write for &mut serde::export::Vec<u8> {
#[cfg(not(feature = "std"))]
impl Write for Vec<u8> {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.extend(buf);
self.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> Result<()> {Ok(())}
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
self.extend_from_slice(buf);
Ok(())
}
#[cfg(not(feature = "std"))]
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
fn bytes(self) -> Bytes<Self> where Self: Sized {
Bytes {
inner: self,
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
#[cfg(feature = "std")]
pub use std::io::Read;
#[cfg(not(feature = "std"))]
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
fn bytes(self) -> Bytes<Self>
where
Self: Sized,
{
Bytes { inner: self }
}
}
#[cfg(feature = "std")]
pub use std::io::Bytes;
#[cfg(not(feature = "std"))]
pub struct Bytes<R> {
inner: R,
@ -76,4 +116,4 @@ impl<R: Read> Iterator for Bytes<R> {
Err(e) => Some(Err(e)),
}
}
}
}

View File

@ -199,10 +199,12 @@ impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
// maps it to fmt::Error
io::Error::new(io::ErrorKind::Other, "fmt error")
}
#[cfg(not(feature = "std"))]
fn io_error<E>(_: E) -> &'static str {
fn io_error<E>(_: E) -> io::Error {
"fmt error"
}
let s = try!(str::from_utf8(buf).map_err(io_error));
try!(self.inner.write_str(s).map_err(io_error));
Ok(buf.len())

View File

@ -1,4 +1,4 @@
use lib::String;
use lib::*;
use super::Value;