rcodec

Crates.iorcodec
lib.rsrcodec
version1.0.1
sourcesrc
created_at2019-09-13 20:14:20.498337
updated_at2020-06-28 21:56:07.479566
descriptionProvides combinators for purely functional, declarative encoding and decoding of binary data.
homepagehttps://github.com/plausiblelabs/rcodec
repositoryhttps://github.com/plausiblelabs/rcodec
max_upload_size
id164649
size93,688
Chris Campbell (chrispcampbell)

documentation

README

rcodec

Build Status Crates.io Docs.rs MIT licensed

This Rust library provides combinators for purely functional, declarative encoding and decoding of binary data. Its design is largely derived from that of the scodec library for Scala.

Usage

Add the following dependencies to your Cargo.toml:

[dependencies]
pl-hlist = "1.0"
rcodec = "1.0"

Then, in your crate:

use pl_hlist::*;
use rcodec::byte_vector;
use rcodec::codec::*;

Examples

The codec module provides a number of predefined codecs. In the following example, we use the uint32 codec to encode a u32 value to a ByteVector representation, and then decode the ByteVector back to its u32 representation:

let codec = uint32;
let v0 = 258u32;
let bv = codec.encode(v0).unwrap();
assert_eq(bv, byte_vector!(0x00, 0x00, 0x01, 0x02));
let v1 = codec.decode(bv).unwrap().value;
assert_eq(v0, v1);

Automatic binding to structs when encoding/decoding is supported via the pl-hlist crate:

#[derive(Debug, PartialEq, Eq, Clone, HListSupport)]
struct TestStruct {
    foo: u8,
    bar: u16
}

let codec = struct_codec!(TestStruct from {uint8} :: {uint16});
let s0 = TestStruct { foo: 7u8, bar: 3u16 };
let bv = codec.encode(&s0).unwrap();
assert_eq(bv, byte_vector!(7, 0, 3));
let s1 = codec.decode(&bv).unwrap().value;
assert_eq(s0, s1);

Here's an example of a more complex codec for a fictitious binary packet format, which uses a number of the built-in combinators:

#[derive(Debug, PartialEq, Eq, Clone, HListSupport)]
struct PacketHeader {
    version: u8,
    port: u16,
    checksum: u16,
    data_len: u16
}

#[derive(Debug, PartialEq, Eq, Clone, HListSupport)]
struct Packet {
    header: PacketHeader,
    flags: u64,
    data: Vec<u8>
}

let magic = byte_vector!(0xCA, 0xFE, 0xCA, 0xFE);

let header_codec = struct_codec!(
    PacketHeader from
    { "version"      => uint8  } ::
    { "port"         => uint16 } ::
    { "checksum"     => uint16 } ::
    { "data_len"     => uint16 }
);

let packet_codec = struct_codec!(
    Packet from
    { "magic"           => constant(&magic) } >>
    { "padding"         => ignore(4)        } >>
    { "header"          => header_codec     } >>= |hdr| {
        hcodec!(
            { "flags"    => uint64                                       } ::
            { "data"     => eager(bytes((hdr.data_len - 8u16) as usize)) })
    }
);

More examples of specific codecs can be found in the tests for src/codec.rs as well as in tests/lib.rs.

License

rcodec is distributed under an MIT license. See LICENSE for more details.

Commit count: 123

cargo fmt