#byte #bytes #binary #io #no-std

no-std byteio

I/O abstractions for bytes

6 releases

0.2.3 Jul 8, 2019
0.2.2 Jul 5, 2019
0.2.1 May 28, 2019
0.1.0 May 19, 2019
0.0.0 May 14, 2019

#1680 in Encoding

Download history 117/week @ 2023-11-05 89/week @ 2023-11-12 81/week @ 2023-11-19 136/week @ 2023-11-26 134/week @ 2023-12-03 266/week @ 2023-12-10 108/week @ 2023-12-17 79/week @ 2023-12-24 190/week @ 2023-12-31 246/week @ 2024-01-07 135/week @ 2024-01-14 135/week @ 2024-01-21 194/week @ 2024-01-28 183/week @ 2024-02-04 68/week @ 2024-02-11 270/week @ 2024-02-18

716 downloads per month
Used in 5 crates (2 directly)


934 lines


I/O abstractions for bytes.
crate version (crates.io) build status (azure) docs (docs.rs) coverage (codecov.io)


byteio is a simple crate that exposes lightweight abstractions for read/write operations on contiguous slices of memory.

At its core byteio is nothing new. A lot of the functionality it offers can be found elsewhere, such as std::io, byteorder, and bytes. What it does offer is:

  • First class no_std support.
  • Reads with lifetimes tied to the underlying buffers.

The crate is based around two core traits: ReadBytes and WriteBytes. Two extension traits which add functionality for reading and writing numbers also have blanket implementations for any types that implement the core traits.


To start using byteio add it to your Cargo.toml like so:

byteio = "0.2"

By default this will active the std feature which enables functionality in the crate which is only available when compiling with the standard library.

To use the crate in a no_std environment you just need to disable this feature. This can be done by adjusting your Cargo.toml:

byteio = { version = "0.2", default-features = false }

The crate has a final feature: alloc. This should be used when you are building in a no_std environment, have an allocator, and want functionality for working with Vec<u8>. You can activate this by adjusting your Cargo.toml again:

byteio = { version = "0.2", default-features = false, features = ["alloc"] }


Manual serialization and deserialization of a simple network packet:

use std::convert::TryInto;

use byteio::prelude::*; // ReadBytes, ReadBytesExt, WriteBytes, WriteBytesExt

/// A packet whose payload is encoded as `[n_msb, n_lsb, b_0, b_1, ..., b_n-1]`.
struct Packet<'a> {
   payload: &'a [u8],

impl<'a> Packet<'a> {
    fn decode<R: ReadBytes<'a>>(mut reader: R) -> byteio::Result<Self> {
        let len: usize = reader.try_read_u16_be()?.into();
        let payload = reader.try_read_exact(len)?;

        Ok(Self { payload })

    fn encode<W: WriteBytes>(&self, mut writer: W) -> byteio::Result<()> {
        let len: u16 = self.payload.len().try_into().unwrap_or_else(|_| !0);



fn main() -> byteio::Result<()> {
    let data = b"\x00\x0Chello, world";

    let packet = Packet::decode(&data[..])?;
    assert_eq!(packet.payload, b"hello, world");

    let mut buf = Vec::new();
    packet.encode(&mut buf)?;
    assert_eq!(&*buf, data);



This project is dual-licensed under either of

at your option.


If you would like to contribute to byteio, experience any issues, or even have features you would like to see implemented, new issues and pull requests are welcomed.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in byteio by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

No runtime deps