net-wire 0.1.0

Allocation-free no_std wire views and codecs for network protocols.
Documentation
use crate::fixtures::{BASIC, OPTIONS};
use net_wire::ParseError;
use net_wire::ipv4::{Ipv4Address, Ipv4Packet, Ipv4PacketMut, Ipv4Protocol};

#[test]
fn fixed_and_option_layouts_are_bounded_and_valid() {
    let p = Ipv4Packet::parse(&BASIC).unwrap();
    assert_eq!(
        (
            p.dscp_ecn(),
            p.total_length(),
            p.identification(),
            p.flags_fragment_offset(),
            p.ttl(),
            p.protocol().raw(),
            p.header_checksum(),
            p.source(),
            p.destination()
        ),
        (
            0,
            20,
            0,
            0,
            64,
            6,
            0xf6e0,
            Ipv4Address::new([192, 0, 2, 1]),
            Ipv4Address::new([192, 0, 2, 2])
        )
    );
    assert_eq!(
        (
            p.options(),
            p.payload(),
            p.as_bytes(),
            p.checksum_is_valid()
        ),
        (&[][..], &[][..], &BASIC[..20], true)
    );
    let q = Ipv4Packet::parse(&OPTIONS).unwrap();
    assert_eq!(
        (
            q.options(),
            q.payload(),
            q.as_bytes().len(),
            q.protocol().raw(),
            q.checksum_is_valid()
        ),
        (&[1, 2, 3, 4][..], &[9, 8, 7, 6][..], 28, 0xfd, true)
    );
}

#[test]
fn parse_errors_and_permissive_capture_fields() {
    assert_eq!(
        Ipv4Packet::parse(&BASIC[..19]),
        Err(ParseError::Truncated {
            minimum: 20,
            available: 19
        })
    );
    let mut b = BASIC;
    b[0] = 0x55;
    assert_eq!(
        Ipv4Packet::parse(&b),
        Err(ParseError::InvalidVersion {
            expected: 4,
            actual: 5
        })
    );
    b = BASIC;
    b[0] = 0x44;
    assert_eq!(
        Ipv4Packet::parse(&b),
        Err(ParseError::InvalidHeaderLength {
            minimum: 20,
            actual: 16
        })
    );
    let mut option_header = OPTIONS;
    option_header[0] = 0x47;
    assert_eq!(
        Ipv4Packet::parse(&option_header[..24]),
        Err(ParseError::Truncated {
            minimum: 28,
            available: 24
        })
    );
    b = BASIC;
    b[2] = 0;
    b[3] = 19;
    assert_eq!(
        Ipv4Packet::parse(&b),
        Err(ParseError::InvalidTotalLength {
            header_length: 20,
            total_length: 19
        })
    );
    b = BASIC;
    b[2] = 0;
    b[3] = 22;
    assert_eq!(
        Ipv4Packet::parse(&b),
        Err(ParseError::Truncated {
            minimum: 22,
            available: 21
        })
    );
    b = BASIC;
    b[10] ^= 1;
    assert!(!Ipv4Packet::parse(&b).unwrap().checksum_is_valid());
    b = BASIC;
    b[6] = 0x80;
    assert_eq!(
        Ipv4Packet::parse(&b).unwrap().flags_fragment_offset(),
        0x8000
    );
}

#[test]
fn mutable_fields_and_checksum_boundary() {
    let mut b = OPTIONS;
    let mut p = Ipv4PacketMut::parse(&mut b).unwrap();
    assert_eq!(
        (
            p.dscp_ecn(),
            p.total_length(),
            p.identification(),
            p.flags_fragment_offset(),
            p.ttl(),
            p.protocol().raw(),
            p.header_checksum(),
            p.source(),
            p.destination()
        ),
        (
            0xab,
            28,
            0x1234,
            0x2005,
            60,
            0xfd,
            0x59c4,
            Ipv4Address::new([192, 0, 2, 1]),
            Ipv4Address::new([198, 51, 100, 2])
        )
    );
    p.set_dscp_ecn(1);
    p.set_identification(2);
    p.set_flags_fragment_offset(3);
    p.set_ttl(4);
    p.set_protocol(Ipv4Protocol::new(5));
    p.set_source(Ipv4Address::new([1, 1, 1, 1]));
    p.set_destination(Ipv4Address::new([2, 2, 2, 2]));
    p.options_mut()[0] = 9;
    assert!(!p.checksum_is_valid());
    p.update_header_checksum();
    assert!(p.checksum_is_valid());
    let c = p.header_checksum();
    p.payload_mut()[0] = 0;
    assert!(p.checksum_is_valid());
    p.set_header_checksum(c);
    p.as_bytes_mut()[1] = 1;
    assert_eq!(p.options(), &[9, 2, 3, 4]);
}