net-wire 0.1.0

Allocation-free no_std wire views and codecs for network protocols.
Documentation
use net_wire::http2::hpack::{
    HpackInteger, HpackIntegerBuildError, HpackIntegerBuilder, HpackIntegerParseError,
};

#[test]
fn hpack_integer_parses_rfc_examples_and_exact_views() {
    let ten = HpackInteger::parse(&[0xea, 0xaa], 5).unwrap();
    assert_eq!(ten.value(), 10);
    assert_eq!(ten.as_bytes(), [0xea]);
    assert_eq!(ten.prefix_bits(), 5);
    assert_eq!(ten.high_bits(), 0xe0);

    let large = HpackInteger::parse(&[0xbf, 0x9a, 0x0a, 0xaa], 5).unwrap();
    assert_eq!(large.value(), 1337);
    assert_eq!(large.as_bytes(), [0xbf, 0x9a, 0x0a]);
    assert_eq!(large.high_bits(), 0xa0);

    let eight_bit = HpackInteger::parse(&[42, 0xaa], 8).unwrap();
    assert_eq!(eight_bit.value(), 42);
    assert_eq!(eight_bit.as_bytes(), [42]);
    assert_eq!(eight_bit.high_bits(), 0);
}

#[test]
fn hpack_integer_parses_saturated_and_overlong_representations() {
    let saturated = HpackInteger::parse(&[0x1f, 0x80, 0x01], 5).unwrap();
    assert_eq!(saturated.value(), 159);
    assert_eq!(saturated.as_bytes(), [0x1f, 0x80, 0x01]);

    let overlong = HpackInteger::parse(&[0x1f, 0x80, 0x00, 0xaa], 5).unwrap();
    assert_eq!(overlong.value(), 31);
    assert_eq!(overlong.as_bytes(), [0x1f, 0x80, 0x00]);
}

#[test]
fn hpack_integer_rejects_invalid_incomplete_and_overflow_representations() {
    assert_eq!(
        HpackInteger::parse(&[], 5),
        Err(HpackIntegerParseError::Incomplete {
            required: 1,
            available: 0,
        })
    );
    assert_eq!(
        HpackInteger::parse(&[0x1f], 5),
        Err(HpackIntegerParseError::Incomplete {
            required: 2,
            available: 1,
        })
    );
    assert_eq!(
        HpackInteger::parse(&[0], 0),
        Err(HpackIntegerParseError::InvalidPrefixBits { prefix_bits: 0 })
    );
    assert_eq!(
        HpackInteger::parse(&[0], 9),
        Err(HpackIntegerParseError::InvalidPrefixBits { prefix_bits: 9 })
    );
    assert_eq!(
        HpackInteger::parse(
            &[
                0x1f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x02
            ],
            5,
        ),
        Err(HpackIntegerParseError::Overflow)
    );
    assert_eq!(
        HpackInteger::parse(
            &[
                0x1f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00
            ],
            5,
        ),
        Err(HpackIntegerParseError::Overflow)
    );
}

#[test]
fn hpack_integer_builder_writes_canonical_bytes_and_preserves_suffix() {
    let mut ten_destination = [0xaa; 4];
    let ten = HpackIntegerBuilder::new(&mut ten_destination, 5, 0xe0, 10)
        .build()
        .unwrap();
    assert_eq!(ten.as_bytes(), [0xea]);
    assert_eq!(ten_destination, [0xea, 0xaa, 0xaa, 0xaa]);

    let mut large_destination = [0xaa; 5];
    let large = HpackIntegerBuilder::new(&mut large_destination, 5, 0xa0, 1337)
        .build()
        .unwrap();
    assert_eq!(large.as_bytes(), [0xbf, 0x9a, 0x0a]);
    assert_eq!(large_destination, [0xbf, 0x9a, 0x0a, 0xaa, 0xaa]);

    let mut eight_bit_destination = [0xaa; 3];
    let eight_bit = HpackIntegerBuilder::new(&mut eight_bit_destination, 8, 0, 42)
        .build()
        .unwrap();
    assert_eq!(eight_bit.as_bytes(), [42]);
    assert_eq!(eight_bit_destination, [42, 0xaa, 0xaa]);
}

#[test]
fn hpack_integer_builder_is_atomic_and_round_trips_u64_max() {
    let mut invalid_prefix = [0xaa; 4];
    let before = invalid_prefix;
    assert_eq!(
        HpackIntegerBuilder::new(&mut invalid_prefix, 0, 0, 1).build(),
        Err(HpackIntegerBuildError::InvalidPrefixBits { prefix_bits: 0 })
    );
    assert_eq!(invalid_prefix, before);

    let mut invalid_high_bits = [0xaa; 4];
    let before = invalid_high_bits;
    assert_eq!(
        HpackIntegerBuilder::new(&mut invalid_high_bits, 5, 0xe1, 1).build(),
        Err(HpackIntegerBuildError::HighBitsOverlap {
            high_bits: 0xe1,
            prefix_bits: 5,
        })
    );
    assert_eq!(invalid_high_bits, before);

    let mut short = [0xaa; 2];
    let before = short;
    assert_eq!(
        HpackIntegerBuilder::new(&mut short, 5, 0xa0, 1337).build(),
        Err(HpackIntegerBuildError::BufferTooShort {
            required: 3,
            available: 2,
        })
    );
    assert_eq!(short, before);

    let mut maximum_destination = [0xaa; 12];
    let maximum = HpackIntegerBuilder::new(&mut maximum_destination, 5, 0xe0, u64::MAX)
        .build()
        .unwrap();
    assert_eq!(maximum.value(), u64::MAX);
    assert_eq!(maximum.high_bits(), 0xe0);
    assert_eq!(
        HpackInteger::parse(maximum.as_bytes(), 5).unwrap().value(),
        u64::MAX
    );
    let maximum_len = maximum.as_bytes().len();
    assert_eq!(maximum_destination[maximum_len..], [0xaa]);
}