#read-write #traits #io-write #data #endianness #packed #packer

bytepack

bytepack offers a Read and Write trait extension generalized for any packed data type

7 unstable releases (3 breaking)

Uses old Rust 2015

0.4.1 May 21, 2017
0.4.0 May 21, 2017
0.3.1 Apr 1, 2017
0.2.0 Mar 20, 2017
0.1.1 Mar 19, 2017

#1854 in Encoding

Download history 108/week @ 2024-05-21 103/week @ 2024-05-28 121/week @ 2024-06-04 95/week @ 2024-06-11 201/week @ 2024-06-18 218/week @ 2024-06-25 45/week @ 2024-07-02 71/week @ 2024-07-09 80/week @ 2024-07-16 83/week @ 2024-07-23 123/week @ 2024-07-30 107/week @ 2024-08-06 98/week @ 2024-08-13 109/week @ 2024-08-20 134/week @ 2024-08-27 103/week @ 2024-09-03

476 downloads per month
Used in 7 crates (4 directly)

MIT license

47KB
958 lines

bytepack

Crates.io Build Status Docs.rs

bytepack is a simple crate which extends the std::io API to be able to read and write any data type in their memory representation. It can be seen as a generalization of the std::io::Read and std::io::Write trait , but operating on a generic parameter T instead of u8. This crate focus on performances by beeing no copy (except in one clearly marked case) and offering methods to read and write arrays.

bytepack offers three trait famillies allowing different endianness control. Unpacker and Packer read and write data in the endianness of the operating system. LEUnpacker and LEPacker always read and write data in little endian while BEUnpacker and BEPacker do the same in big endian. They all conform to the same API which is copied from the one of std::io. This means switching from one endianness to another can be done by simply bringing a different trait in scope.

Because bytepack is not a serialization library, it cannot read and write complex types like Vec, Rc, etc. directly from a Reader or to Writer. Indeed those types do not contain the underlying data directly packed inside but rather hold a reference or a pointer to it. To identify types which holds their data "packed" together, the Packed trait is used. Additionnaly it provides a in-place endianness switching method. One can implement this trait for the data types deemed safe to read and write. An automatic derive for structures made only of types implementing Packed is also implemented in the bytepack_derive crate.

Examples

Here are two functions which can serialize and deserialize a Vec<f32>:

extern crate bytepack;

use std::fs::File;
use std::iter::repeat;

use bytepack::{LEPacker, LEUnpacker};

fn write_samples(file: &str, samples: &Vec<f32>) {
    let mut file = File::create(file).unwrap();
    file.pack(samples.len() as u32).unwrap();
    file.pack_all(&samples[..]).unwrap();
}

fn read_samples(file: &str) -> Vec<f32> {
    let mut file = File::open(file).unwrap();
    let num_samples : u32 = file.unpack().unwrap();
    let mut samples : Vec<f32> = repeat(0f32).take(num_samples as usize).collect();
    file.unpack_exact(&mut samples[..]).unwrap();
    return samples;
}

Thanks to the genericity of the Packed trait we could make the previous function generic:

extern crate bytepack;

use std::fs::File;

use bytepack::{LEPacker, Packed};

fn write_vec<T: Packed + Clone>(file: &str, samples: &Vec<T>) {
    let mut file = File::create(file).unwrap();
    file.pack(samples.len() as u32).unwrap();
    file.pack_all(&samples[..]).unwrap();
}

Because we can derive Packed for our own struct, we can use them with our own types:

extern crate bytepack;
#[macro_use]
extern crate bytepack_derive;

use std::fs::File;

use bytepack::{LEPacker, Packed};

#[derive(Packed, Clone)]
struct Vertex<T: Packed> {
    x: T,
    y: T,
    z: T
}

fn write_vec<T: Packed + Clone>(file: &str, samples: &Vec<T>) {
    let mut file = File::create(file).unwrap();
    file.pack(samples.len() as u32).unwrap();
    file.pack_all(&samples[..]).unwrap();
}

fn main() {
    let square : Vec<Vertex<f32>> = vec![
        Vertex{x: 0.0, y: 0.0, z: 0.0},
        Vertex{x: 1.0, y: 0.0, z: 0.0},
        Vertex{x: 1.0, y: 1.0, z: 0.0},
        Vertex{x: 0.0, y: 1.0, z: 0.0},
    ];

    write_vec("square.raw", &square);
}

Dependencies

~1.5MB
~42K SLoC