Simple bit-level protocol definitions in Rust.

Overview

bin-proto

crates tests docs.rs license

Simple & fast structured bit-level binary co/dec in Rust.

An improved and modernized fork of protocol. A more efficient but (slightly) less feature-rich alternative to deku.

This crate adds a trait (and a custom derive for ease-of-use) that can be implemented on types, allowing structured data to be sent and received from any binary stream. It is recommended to use bitstream_io if you need bit streams, as their BitRead and BitWrite traits are being used internally.

Example

Add this to your Cargo.toml:

[dependencies]
bin-proto = "0.4"

And then define a type with the #[derive(bin_proto::Protocol)] attribute.

use bin_proto::{Protocol, ProtocolNoCtx};

#[derive(Debug, Protocol, PartialEq)]
#[protocol(discriminant_type = "u8")]
#[protocol(bits = 4)]
enum E {
    V1 = 1,
    #[protocol(discriminant = "4")]
    V4,
}

#[derive(Debug, Protocol, PartialEq)]
struct S {
    #[protocol(bits = 1)]
    bitflag: bool,
    #[protocol(bits = 3)]
    bitfield: u8,
    enum_: E,
    #[protocol(write_value = "self.arr.len() as u8")]
    arr_len: u8,
    #[protocol(length = "arr_len as usize")]
    arr: Vec<u8>,
    #[protocol(flexible_array_member)]
    read_to_end: Vec<u8>,
}

assert_eq!(
    S::from_bytes(&[
        0b1000_0000 // bitflag: true (1)
       | 0b101_0000 // bitfield: 5 (101)
           | 0b0001, // enum_: V1 (0001)
        0x02, // arr_len: 2
        0x21, 0x37, // arr: [0x21, 0x37]
        0x01, 0x02, 0x03, // read_to_end: [0x01, 0x02, 0x03]
    ], bin_proto::ByteOrder::BigEndian).unwrap(),
    S {
        bitflag: true,
        bitfield: 5,
        enum_: E::V1,
        arr_len: 2,
        arr: vec![0x21, 0x37],
        read_to_end: vec![0x01, 0x02, 0x03],
    }
);

You can implement Protocol on your own types, and parse with context:

use bin_proto::Protocol;

pub struct Ctx;

pub struct NeedsCtx;

impl Protocol<Ctx> for NeedsCtx {
    fn read(
        _read: &mut dyn bin_proto::BitRead,
        _byte_order: bin_proto::ByteOrder,
        _ctx: &mut Ctx,
    ) -> Result<Self, bin_proto::Error> {
        // Use ctx here
        Ok(Self)
    }

    fn write(
        &self,
        _write: &mut dyn bin_proto::BitWrite,
        _byte_order: bin_proto::ByteOrder,
        _ctx: &mut Ctx,
    ) -> Result<(), bin_proto::Error> {
        // Use ctx here
        Ok(())
    }
}

#[derive(Protocol)]
#[protocol(ctx = "Ctx")]
pub struct WithCtx(NeedsCtx);

WithCtx(NeedsCtx)
    .bytes_ctx(bin_proto::ByteOrder::LittleEndian, &mut Ctx)
    .unwrap();

Performance / Alternatives

This crate's main alternative is deku, and binrw for byte-level protocols.

bin-proto is significantly faster than deku in all of the tested scenarios. The units for the below table are ns/iter, taken from github CI. You can find the benchmarks in the bench directory.

Read enum Write enum Read Vec Write Vec Read IPv4 header Write IPv4 header
bin-proto 21 93 738 821 151 141
deku 67 227 3,041 9,705 2,468 821

Roadmap

The following features are planned:

  • Bit/byte alignment
  • no_std support (only after bitstream_io supports it)
You might also like...
syntax-level async join enabling branching control flow and shared mutable borrow

enjoin enjoin's async join macros operate at the syntax level. It allows you to... break, continue, and return out of async code running in a join for

Rust bindings to the Wolfram Symbolic Transport Protocol (WSTP)

wstp Bindings to the Wolfram Symbolic Transfer Protocol (WSTP) library. This crate provides a set of safe and ergonomic bindings to the WSTP library,

Rust lib for fetching official protoc (Protocol Buffer compiler) releases

protoc-fetcher Rust library for fetching official Protocol Buffer compiler (protoc) releases, pegged to a specific version. protoc-fetcher downloads a

Rust libraries for Bluesky's AT Protocol services. NOT STABLE (yet)

ATrium ATrium is a collection of Rust libraries designed to work with the AT Protocol, providing a versatile and coherent ecosystem for developers. Th

SDK for the Portfolio protocol written in rust.

portfolio-rs Minimalist toolkit for building rust applications on top of the portfolio protocol. Installation [Required] Foundry. Source. If not insta

Precio is a Rust library that implements the Precio protocol for computing private layered histograms and sums.

Overview of Precio Precio is a Rust implementation of the protocol described in eprint.iacr.org/2021/1490. The goal of the protocol is to enable an an

Manas project aims to create a modular framework and ecosystem to create robust storage servers adhering to Solid protocol in rust.

मनस् | Manas Solid is a web native protocol to enable interoperable, read-write, collaborative, and decentralized web, truer to web's original vision.

A learning project/fun experiment in internet protocol

Piper a learning project/fun experiment in internet protocol Version 0.4.0 (SEMVER) Goals Piper is Simple. A page is a page. There are no secondary re

Simple autoclicker written in Rust, to learn the Rust language.

RClicker is an autoclicker written in Rust, written to learn more about the Rust programming language. RClicker was was written by me to learn more ab

Comments
  • Discriminant and repr

    Discriminant and repr

    I'm looking into bin-proto as an alternative to deku (since I like performance :) ) for a rather complex binary protocol: https://github.com/vhdirk/dash7-rs

    One thing that kind of bugs me about deku, and is also present in bin-proto, is the need to specify the discriminant type and value using annotations, instead of Rust's built in explicit discriminant definitions, combined with repr(uX).

    So I am curious why annotations are needed at all? And if you would be willing to accept contributions that make using a 'native' discriminant possible. For one thing, it would make my life a little easier when creating bindings.

    opened by vhdirk 4
  • WIP: conditionally read Option<T>

    WIP: conditionally read Option

    So, I really like the readability of bin-proto's internals. But feature-wise, it's not where I'd need it to be to replace deku.

    For one, I'd like the ability to conditionally read an Option, based on an external field. Kinda like externally length prefixed, but for Option.

    I started making it, but I quickly realized that, in order for it to be compatible with other attributes, like bits, it start's getting somewhat complicated. And from what I can tell, with the current infrastructure, I'd need a trait Conditional and ConditionalWithBitfield or something alike? That feels somewhat clunky.

    I guess it can be easily solved using the new Ctx system, but I'd like for it to be a first-class citizen.

    What's your opinion on this?

    opened by vhdirk 7
Releases(v0.4.0)
  • v0.4.0(May 18, 2024)

    • Delete EnumExt
    • Bump dependencies, and rust version to 2021
    • Make lifetime generics work
    • Handle context using generics instead of Any
    • Improve derive macro hygiene
    • Improve derive macro error reporting
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Mar 28, 2024)

    • Implement ExternallyLengthPrefixed on HashMap, BTreeMap, String
    • Do not implement Protocol on char, range, HashMap, BTreeMap
    • Implement protocol on Ipv4Addr and Ipv6Addr, (T0, ), (), Box
    • Rename Enum trait to EnumExt
    • Delete Settings, replace with ByteOrder
    • Clean up Error
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Mar 27, 2024)

    • Add context to all parse functions
    • Remove #[repr(...)], instead specify repr in #[protocol(discriminant = "...")]
    • Remove Hints, LengthPrefixed, etc.
    • Add #[protocol(write_value = "<expr>")] for automatically writing arbitrary element value
    • Replace #[protocol(length_prefix(<kind>(<field>)))] with #[protocol(length = "<expr>")]
    • Check attribute applicability in every context
    • Require discriminants type to be specified for an enum
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Mar 26, 2024)

Owner
null
Rust library of custom number malarkey, including variable-bit-width integers

Numberwang The Numberwang crate is a library of custom number types and functionality, including variable-bit-width integers. It is named after the fi

Dan Williams 3 Nov 12, 2024
Isn't it time to be a bit nicer to rustc?

politeness-macro Aren't we all too rude to computers? Isn't it time to bring a bit more politeness into our programming? Shouldn't we be a bit nicer t

Rin 6 Mar 11, 2022
Bitpack a boolean into a pointer using bit magic.

ptr-bool tl;dr: a pointer and boolean with the same size as a pointer. A convenience crate used to bitpack a boolean and pointer into the same eight b

Zack 2 Oct 24, 2022
fanum tax 64-bit integers with LEB128

rizz64 Fanum* tax 64-bit integers. * Fanum is a popular streamer who taxes his friends by taking bites of their food. This crate provides an efficient

Matthew Kim 11 May 22, 2024
Simple and fast proxy checker that include protocol validation;

Open Proxies ⭐️ Leave me a start please ⭐️ it will motivate me to continue maintaining and adding futures About | Technologies | Requirements | Starti

kmoz000 3 Nov 29, 2022
Rust Imaging Library: A high-level Rust imaging crate.

ril Rust Imaging Library: A performant and high-level Rust imaging crate. Documentation • Crates.io • Discord What's this? This is a Rust crate design

Jay3332 18 Jan 5, 2023
Low level access to T-Head Xuantie RISC-V processors

XuanTie Low level access to T-Head XuanTie RISC-V processors Contributing We welcome contribution! Please send an issue or pull request if you are rea

Luo Jia 30 Aug 24, 2022
Gecko is a high-level, general-purpose programming language built on top of the LLVM project.

Gecko is a high-level, general-purpose programming language built on top of the LLVM project. Gecko Technology & principles Gecko is a general-purpose

Gecko 19 Oct 3, 2022
Higher-level toolkit for MSDF text rendering

MSDF Toolkit Higher-level toolkit for MSDF text rendering About MSDF - an abbreviation of Multi-channel Signed Distance Field. In short, an efficient

null 2 Aug 19, 2022
Low-level CPU and register abstractions for the N64 console

Description This crate is a low-level abstraction (aka a Peripheral Access Crate) over the CPU and memory-mapped registers available on the Nintendo 6

Luke Stadem 5 Dec 17, 2022