[][src]Crate not_io

Provides Read and Write alternatives on no_std while being compatible with the full traits from std when allowed.

Motivation

The file parser ecosystem of Rust is more or less split across crates that use no_std and crates that do not, as well as between crates using alloc and no-alloc (and the largely overlapping zero-copy) crates. This has several reasons:

  • The std::io::Read and std::io::Write traits require an allocator due to their internal implementation and were not written to be OS independent.
  • Before 1.36 it was not possible to depend on alloc without std.
  • The lack of specialization makes it hard to be both generic over implementors of the standard traits while still allowing use when those traits are not available. This is in particular also since several types (e.g. &[u8]) implement those traits but would obviously be useful as byte sources and sinks even when they are unavailable.

Usage guide

This crate assumes you have a structure declared roughly as follows:


struct Decoder<T> {
    reader: T,
}

impl<T: std::io::Read> Decoder<T> {
    fn next(&mut self) -> Result<SomeItem, std::io::Error> {
        let mut buffer = vec![];
        self.reader.read_to_end(&mut buffer)?;
    }
}

There is only one necessary change, be sure to keep the std feature enabled for now. This should not break any code except if you relied on the precise type T in which case you will need to use a few derefs and/or into_inner.

use not_io::AllowStd;

struct Decoder<T> {
    reader: AllowStd<T>,
}

And finally you can add to your crate a new default feature which enables the std/alloc feature of this crate, and conditionally active your existing interfaces only when that feature is active. Then add a few new impls that can be used even when the feature is inactive.

use not_io::AllowStd;

struct Decoder<T> {
    reader: AllowStd<T>,
}

/// The interface which lets the caller select which feature to turn on.
impl<T> Decoder<T>
where
    AllowStd<T>: not_io::Read
{
    fn no_std_next(&mut self) -> Result<SomeItem, not_io::Error> {
    }
}

/// An interface for pure no_std use with caller provide no_std reader.
impl<T> Decoder<T>
where
    T: not_io::Read
{
    fn not_io_next(&mut self) -> Result<SomeItem, not_io::Error> {
        let reader = &mut self.reader.0;
    }
}

Structs

AllowStd

A simple new type wrapper holding a potential reader or writer.

Error

Traits

Read
Write

Type Definitions

Result