bitbuffer 0.11.3

Reading bit sequences from a byte slice
Documentation
use bitbuffer::{
    BigEndian, BitRead, BitReadBuffer, BitReadStream, BitWrite, BitWriteStream, LittleEndian,
};
use std::fmt::Debug;

#[track_caller]
fn roundtrip<
    T: BitRead<'static, BigEndian>
        + BitWrite<BigEndian>
        + BitRead<'static, LittleEndian>
        + BitWrite<LittleEndian>
        + Debug
        + PartialEq,
>(
    val: T,
) {
    {
        let mut data = Vec::new();
        let size = {
            let mut stream = BitWriteStream::new(&mut data, LittleEndian);
            stream.write(&val).unwrap();
            stream.bit_len()
        };
        let mut read = BitReadStream::new(BitReadBuffer::new_owned(data, LittleEndian));
        assert_eq!(val, read.read().unwrap());
        assert_eq!(size, read.pos());
    }
    {
        let mut data = Vec::new();
        let size = {
            let mut stream = BitWriteStream::new(&mut data, BigEndian);
            stream.write(&val).unwrap();
            stream.bit_len()
        };
        let mut read = BitReadStream::new(BitReadBuffer::new_owned(data, BigEndian));
        assert_eq!(val, read.read().unwrap());
        assert_eq!(size, read.pos());
    }
}

#[test]
fn test_basic_struct() {
    #[derive(Debug, PartialEq, BitRead, BitWrite)]
    struct Foo {
        int: u32,
        float: f64,
        #[size = 2]
        smaller_int: u8,
        signed: i32,
        #[size = 3]
        smaller_signed: i32,
        dynamic_string: String,
        #[size = 3]
        fixed_string: String,
    }
    roundtrip(Foo {
        int: 1234,
        float: 10.2,
        smaller_int: 3,
        signed: -3,
        smaller_signed: -1,
        dynamic_string: "Foobar".to_string(),
        fixed_string: "asd".to_string(),
    });
}

#[test]
fn test_bare_enum() {
    #[derive(Debug, PartialEq, BitRead, BitWrite)]
    #[discriminant_bits = 4]
    enum Enum {
        A,
        B,
        C,
        D,
    }
    roundtrip(Enum::A);
    roundtrip(Enum::B);
    roundtrip(Enum::C);
    roundtrip(Enum::D);
}

#[test]
fn test_field_enum() {
    #[derive(Debug, PartialEq, BitRead, BitWrite)]
    struct CompoundVariant(#[size = 15] u16, bool);

    #[derive(Debug, PartialEq, BitRead, BitWrite)]
    #[discriminant_bits = 4]
    enum Enum {
        A,
        B(String),
        C(f32),
        D(#[size = 15] i64),
        E(CompoundVariant),
    }
    roundtrip(Enum::A);
    roundtrip(Enum::B("foobar".into()));
    roundtrip(Enum::C(12.0));
    roundtrip(Enum::D(-12345));
    roundtrip(Enum::E(CompoundVariant(6789, true)));
}

#[test]
fn test_array() {
    roundtrip([1, 2, 3, 4, 5]);
    roundtrip([String::from("asd"), String::from("foobar")]);
}

#[test]
fn test_tuple() {
    roundtrip((1, false));
    roundtrip((1, 10.12, String::from("asd")));
}