lightpack 0.2.8

A lightweight, no-std binary serialization library
Documentation
use byteorder::{ByteOrder, BigEndian, LittleEndian};
use lightpack::{Pack, Size, extra::{BE, LE, PackSize}};

fn pack_vec<B, P>(value: P) -> Vec<u8> where B: ByteOrder, P: Pack {
    let mut buffer = vec![0u8; P::SIZE];
    value.pack::<B>(&mut buffer);
    buffer
}

#[test]
fn unsigned_ints() {
    assert_eq!(pack_vec::<BigEndian, u8>(0), vec![0]);
    assert_eq!(pack_vec::<BigEndian, u16>(4), vec![0, 4]);
    assert_eq!(pack_vec::<LittleEndian, u16>(4), vec![4, 0]);
    assert_eq!(pack_vec::<BigEndian, u16>(258), vec![1, 2]);
    assert_eq!(pack_vec::<LittleEndian, u16>(258), vec![2, 1]);
    assert_eq!(pack_vec::<LittleEndian, u32>(1048), vec![24, 0b100, 0, 0]);
    assert_eq!(pack_vec::<BigEndian, u32>(1048), vec![0, 0, 0b100, 24]);
}

#[test]
fn signed_ints() {
    assert_eq!(pack_vec::<BigEndian, i8>(0), vec![0]);
    assert_eq!(pack_vec::<BigEndian, i8>(-1), vec![255]);
    assert_eq!(pack_vec::<LittleEndian, i8>(-2), vec![254]);
    assert_eq!(pack_vec::<BigEndian, i16>(256), vec![1, 0]);
    assert_eq!(pack_vec::<LittleEndian, i16>(256), vec![0, 1]);
}

#[test]
fn basic_structs() {
    #[derive(Size, Pack, Clone, Copy)]
    #[allow(dead_code)]
    struct X {
        x: u8,
        y: u16,
    }

    #[derive(Size, Pack, Clone, Copy)]
    #[allow(dead_code)]
    struct Y {
        x0: X,
        x1: X,
        x2: bool,
    }

    #[derive(Size, Pack, Clone, Copy)]
    struct Tuple(X, Y);

    #[derive(Size, Pack, Clone, Copy)]
    struct Unit;

    let x0 = X { x: 3, y: 4 };
    let x1 = X { x: 2, y: 8 };
    let y = Y { x0, x1, x2: true };

    assert_eq!(pack_vec::<BigEndian, _>(x0), vec![3, 0, 4]);
    assert_eq!(pack_vec::<LittleEndian, _>(x1), vec![2, 8, 0]);
    assert_eq!(pack_vec::<BigEndian, _>(y), vec![3, 0, 4, 2, 0, 8, 1]);
    assert_eq!(pack_vec::<BigEndian, _>(Tuple(x0, y)), vec![3, 0, 4, 3, 0, 4, 2, 0, 8, 1]);
    assert_eq!(pack_vec::<BigEndian, _>(Unit), vec![]);
}

#[test]
fn generic_structs() {
    #[derive(Size, Pack)]
    #[allow(dead_code)]
    struct Wrap<T>(T);

    #[derive(Size, Pack)]
    #[allow(dead_code)]
    struct Pair<L, R> {
        left: L,
        right: R,
    }

    #[derive(Size, Pack)]
    #[allow(dead_code)]
    struct HasField {
        wrap: Wrap<u32>,
    }

    #[derive(Size, Pack)]
    #[allow(dead_code)]
    struct HasGenericField<T> {
        wrap: Wrap<T>,
        x: bool,
    }

    assert_eq!(pack_vec::<LittleEndian, _>(Wrap(3i32)), vec![3, 0, 0, 0]);
    assert_eq!(pack_vec::<BigEndian, _>(Wrap(4u16)), vec![0, 4]);
    assert_eq!(pack_vec::<BigEndian, _>(Pair { left: -4i16, right: 3u8 }), pack_vec::<BigEndian, _>((-4i16, 3u8)));
    assert_eq!(pack_vec::<BigEndian, _>(HasField { wrap: Wrap(4u32) }), vec![0, 0, 0, 4]);
    assert_eq!(pack_vec::<LittleEndian, _>(HasGenericField { wrap: Wrap(false), x: true }), vec![0, 1]);
}

#[test]
fn primitive_enums() {
    #[derive(Size, Pack, Clone, Copy)]
    #[repr(u8)]
    #[allow(dead_code)]
    enum X {
        A = 1,
        B = 4,
        C = 8,
    }

    #[derive(Size, Pack, Clone, Copy)]
    #[repr(i32)]
    #[allow(dead_code)]
    enum Y {
        A = -9,
    }

    assert_eq!(pack_vec::<BigEndian, _>(X::A), vec![1]);
    assert_eq!(pack_vec::<BigEndian, _>(X::B), vec![4]);
    assert_eq!(pack_vec::<BigEndian, _>(X::C), vec![8]);
}

#[test]
fn arrays() {
    assert_eq!(pack_vec::<BigEndian, _>([0u32; 0]), vec![]);
    assert_eq!(pack_vec::<BigEndian, _>([-1i8]), vec![255]);
    assert_eq!(pack_vec::<BigEndian, _>([16u32; 3]), vec![0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16]);
    assert_eq!(pack_vec::<BigEndian, _>([3u8, 4, 1, 0, 2]), vec![3, 4, 1, 0, 2]);
    assert_eq!(pack_vec::<LittleEndian, _>([2i16, 3, -1]), vec![2, 0, 3, 0, 255, 255]);
    assert_eq!(pack_vec::<LittleEndian, _>([(true, false), (false, false), (true, true)]), vec![1, 0, 0, 0, 1, 1]);
}

#[test]
fn fixed_endianness() {
    assert_eq!(pack_vec::<BigEndian, _>(BE(45u16)), pack_vec::<BigEndian, u16>(45));
    assert_eq!(pack_vec::<LittleEndian, _>(BE(45u16)), pack_vec::<BigEndian, u16>(45));
    assert_eq!(pack_vec::<BigEndian, _>(LE(45u16)), pack_vec::<LittleEndian, u16>(45));
    assert_eq!(pack_vec::<LittleEndian, _>(LE(45u16)), pack_vec::<LittleEndian, u16>(45));
}

#[test]
fn mixed_endianness() {
    #[derive(Size, Pack)]
    struct Mixed {
        le: LE<u16>,
        be: BE<u16>,
    }

    assert_eq!(pack_vec::<BigEndian, _>(Mixed { le: LE(256), be: BE(256) }), vec![0, 1, 1, 0]);
    assert_eq!(pack_vec::<LittleEndian, _>(Mixed { le: LE(256), be: BE(256) }), vec![0, 1, 1, 0]);
}

#[test]
fn test_pack_size() {
    let mut buffer = [0u8; 4];
    assert_eq!(3u16.pack_size::<BigEndian>(&mut buffer), u16::SIZE);
    assert_eq!(2u32.pack_size::<BigEndian>(&mut buffer), u32::SIZE);
}