Skip to content
Snippets Groups Projects
packet.rs 24.2 KiB
Newer Older
use core::fmt::Debug;

use crc::{Crc, CRC_16_IBM_SDLC};

use crate::{
Stephen D's avatar
Stephen D committed
    buffer::{Buffer, BufferOverflow},
    error::{CommentError, DecodeError, EncodeError},
Stephen D's avatar
Stephen D committed
    interleaver, ldpc, utf8,
    whisker::{
        Arbitrary, Comment, Destination, Gps, Identification, Route, Timestamp,
        ValidatedWhiskerIter, Whisker, WhiskerIter, COMMENT_TYPE,
Stephen D's avatar
Stephen D committed
    whitener,
};

const X25: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_SDLC);

macro_rules! uniq_whisker {
    ($t:meta) => {
        ::paste::paste! {
            pub fn [<$t:lower>](&self) -> Option<$t> {
                self.iter().find_map(|w| match w {
                    Whisker::$t(x) => Some(x),
                    _ => None,
                })
            }

            pub fn [<add_ $t:lower>](&mut self, w: $t) -> Result<(), EncodeError> {
                if self.[<$t:lower>]().is_some() {
                    return Err(EncodeError::DuplicateData);
                }

                try_lock(&mut self.buf, |data| {
					let mut buf = [0; 256];
                    // safe to unwrap since we know we have enough space
                    let out = w.encode(&mut buf).unwrap();

                    data.try_push(crate::whisker::[<$t:upper _TYPE>]).ok().ok_or(EncodeError::CatsOverflow)?;
                    data.try_extend_from_slice(out).ok().ok_or(EncodeError::CatsOverflow)?;

                    Ok(())
                })?;

                Ok(())
            }
			pub fn [<clear_ $t:lower>](&mut self) {
				self.clear_by_type(crate::whisker::[<$t:upper _TYPE>], false);
			}
        }
    };
}

macro_rules! poly_whisker {
    ($t: meta) => {
        ::paste::paste! {
            pub fn [<$t:lower _iter>](&self) -> core::iter::FilterMap<ValidatedWhiskerIter, fn(Whisker) -> Option<$t>> {
				fn filt(w: Whisker) -> Option<$t> {
                    match w {
                        Whisker::$t(x) => Some(x),
                        _ => None
                    }
				}

                self.iter().filter_map(filt)
            }

			pub fn [<add_ $t:lower>](&mut self, w: $t) -> Result<(), EncodeError> {
				try_lock(&mut self.buf, |data| {
					let mut buf = [0; 256];
                    // safe to unwrap since we know we have enough space
                    let out = w.encode(&mut buf).unwrap();

                    data.try_push(crate::whisker::[<$t:upper _TYPE>]).ok().ok_or(EncodeError::CatsOverflow)?;
                    data.try_extend_from_slice(out).ok().ok_or(EncodeError::CatsOverflow)?;

                    Ok(())
                })?;

                Ok(())
			}

			pub fn [<clear_ $t:lower>](&mut self) {
				self.clear_by_type(crate::whisker::[<$t:upper _TYPE>], true);
			}
Stephen D's avatar
Stephen D committed
/// N is the maximum packet size we can handle
/// Panics if N >= 8191
Stephen D's avatar
Stephen D committed
pub struct Packet<'a, const N: usize> {
    buf: Buffer<'a, N>,
Stephen D's avatar
Stephen D committed
impl<'a, const N: usize> Packet<'a, N> {
    pub fn new(buf: &'a mut [u8; N]) -> Self {
        Self { buf: buf.into() }
    }

Stephen D's avatar
Stephen D committed
    pub fn clone_backing<'b>(&self, buf: &'b mut [u8; N]) -> Packet<'b, N> {
        Packet {
            buf: self.buf.clone_backing(buf),
        }
    }

Stephen D's avatar
Stephen D committed
    /// Expects bytes in the `buf`
    /// `buf` is used as the backing buffer for the Packet
    pub fn decode(buf: Buffer<'a, N>) -> Result<Self, DecodeError> {
Stephen D's avatar
Stephen D committed
        assert!(N <= 8191);

        // validate the data
Stephen D's avatar
Stephen D committed
        for w in WhiskerIter::new(&buf) {
Stephen D's avatar
Stephen D committed
        let comment_iter = WhiskerIter::new(&buf)
Stephen D's avatar
Stephen D committed
            .filter_map(|w| match w.unwrap() {
                Whisker::Comment(c) => Some(c.internal_data().clone()),
                _ => None,
            })
            .flatten();

        if !utf8::validate(comment_iter) {
            return Err(DecodeError::InvalidComment);
        }

Stephen D's avatar
Stephen D committed
        Ok(Self { buf })
    }

    pub fn encode(&self) -> &[u8] {
Stephen D's avatar
Stephen D committed
        &self.buf
    }

    /// Directly after the CRC block in The Pipeline
Stephen D's avatar
Stephen D committed
    pub fn semi_encode(mut self) -> Result<Buffer<'a, N>, (EncodeError, Self)> {
        let crc = X25.checksum(&self.buf).to_le_bytes();
Stephen D's avatar
Stephen D committed
        let res: Result<(), BufferOverflow> = try_lock(&mut self.buf, |data| {
            data.try_push(crc[0])?;
            data.try_push(crc[1])?;

            Ok(())
        });

        match res {
Stephen D's avatar
Stephen D committed
            Ok(()) => Ok(self.buf),
            Err(_) => Err((EncodeError::CatsOverflow, self)),
        }
    }

    /// Directly after the CRC block in The Pipeline
Stephen D's avatar
Stephen D committed
    /// Expects bytes in the `buf`
    /// `buf` is used as the backing buffer for the Packet
    pub fn semi_decode(mut buf: Buffer<'a, N>) -> Result<Self, DecodeError> {
Stephen D's avatar
Stephen D committed
        let crc1 = buf.pop().ok_or(DecodeError::UnexpectedEndOfInput)?;
        let crc0 = buf.pop().ok_or(DecodeError::UnexpectedEndOfInput)?;
        let crc_expected = u16::from_le_bytes([crc0, crc1]);
Stephen D's avatar
Stephen D committed
        let crc_actual = X25.checksum(&buf);

        if crc_expected != crc_actual {
            return Err(DecodeError::CrcMismatch);
        }

Stephen D's avatar
Stephen D committed
        Self::decode(buf)
Stephen D's avatar
Stephen D committed
    /// Encodes packet for transmission on the air.
    /// Includes the data length L, but does not include the preamble or sync word.
    pub fn fully_encode(self, out: &mut Buffer<N>) -> Result<(), EncodeError> {
Stephen D's avatar
Stephen D committed
        let mut data = self.semi_encode().map_err(|(err, _)| err)?;
        whitener::whiten(&mut data);
        ldpc::encode(&mut data)?;
        // safe to unwrap - length must be below 8191
        out.try_extend_from_slice(&u16::try_from(data.len()).unwrap().to_le_bytes())
            .map_err(|_| EncodeError::CatsOverflow)?;
        interleaver::interleave(&data, out)?;
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
    }

    /// Decodes packet that was received over the air.
    /// Packet shouldn't have preamble, sync word, or data langth L.
Stephen D's avatar
Stephen D committed
    /// Expects bytes in the `buf`
    /// `buf` is used as the backing buffer for the Packet
    pub fn fully_decode(data: &[u8], buf: &'a mut [u8; N]) -> Result<Self, DecodeError> {
        let mut buf = Buffer::new_empty(buf);
        interleaver::uninterleave(data, &mut buf).map_err(|_| DecodeError::Overflow)?;
        ldpc::decode(&mut buf).ok_or(DecodeError::LdpcError)?;
        whitener::whiten(&mut buf);
Stephen D's avatar
Stephen D committed

        Self::semi_decode(buf)
    pub fn iter(&self) -> ValidatedWhiskerIter {
        ValidatedWhiskerIter::new(&self.buf)
    uniq_whisker!(Identification);
    uniq_whisker!(Timestamp);
    uniq_whisker!(Gps);
    uniq_whisker!(Route);
    poly_whisker!(Destination);
    poly_whisker!(Arbitrary);
    pub fn comment<'b>(&self, buf: &'b mut [u8]) -> Result<&'b str, CommentError> {
        let iter = self.iter().filter_map(|w| match w {
            Whisker::Comment(c) => Some(c),
            _ => None,
        });

        let mut i = 0;
        let mut has_comment = false;
        for c in iter {
            has_comment = true;
            let data = c.internal_data();
            buf.get_mut(i..(i + data.len()))
                .ok_or(CommentError::BufferOverflow)?
                .copy_from_slice(data);
        if !has_comment {
            return Err(CommentError::NoComment);
        }

Stephen D's avatar
Stephen D committed
        // Safe to unwrap since the comment was pre-validated
        Ok(core::str::from_utf8(&buf[0..i]).unwrap())
    }

    pub fn add_comment(&mut self, comment: &str) -> Result<(), EncodeError> {
        if self.iter().any(|w| matches!(w, Whisker::Comment(_))) {
            // we already have a comment
            return Err(EncodeError::DuplicateData);
        }

        try_lock(&mut self.buf, |data| {
            let mut comment = comment.as_bytes();

            while comment.len() > 255 {
                let c = Comment::new(&comment[0..255]).unwrap();
                let mut buf = [0; 256];
                let out = c.encode(&mut buf).unwrap();

                data.try_push(COMMENT_TYPE)
                    .map_err(|_| EncodeError::CatsOverflow)?;
                data.try_extend_from_slice(out)
                    .map_err(|_| EncodeError::CatsOverflow)?;

                comment = &comment[255..];
            }

            let c = Comment::new(comment).unwrap();
            let mut buf = [0; 256];
            let out = c.encode(&mut buf).unwrap();

            data.try_push(COMMENT_TYPE)
                .map_err(|_| EncodeError::CatsOverflow)?;
            data.try_extend_from_slice(out)
                .map_err(|_| EncodeError::CatsOverflow)?;

            Ok(())
        })?;

        Ok(())
    }

    pub fn clear_comment(&mut self) {
        self.clear_by_type(COMMENT_TYPE, true);
    }

    fn clear_by_type(&mut self, whisker_type: u8, all: bool) {
        let mut i = 0;
        while i < self.buf.len() {
            let t = self.buf[i];
            let step = usize::from(self.buf[i + 1]) + 2;

            if t == whisker_type {
                self.buf.drain(i, i + step);

                if !all {
                    return;
                }
            } else {
                i += step;
            }
        }
    }
Stephen D's avatar
Stephen D committed
impl<'a, const N: usize> Debug for Packet<'a, N> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_list()
            .entries(ValidatedWhiskerIter::new(&self.buf))
            .finish()
    }
}

// if the function returns an error, we roll back the array
// by rolling it back, we really just pop bytes off the end until the length matches
Stephen D's avatar
Stephen D committed
fn try_lock<'a, const N: usize, T, E, F: Fn(&mut Buffer<'a, N>) -> Result<T, E>>(
    buf: &mut Buffer<'a, N>,
    f: F,
) -> Result<T, E> {
Stephen D's avatar
Stephen D committed
    let len = buf.len();
Stephen D's avatar
Stephen D committed
    match f(buf) {
        Ok(x) => Ok(x),
        Err(e) => {
Stephen D's avatar
Stephen D committed
            buf.truncate(len);
    use arrayvec::ArrayString;
    #[test]
    fn dest() {
        let d1 = Destination::new(false, 7, "CALL1", 23).unwrap();
        let d2 = Destination::new(true, 23, "CALL2", 2).unwrap();

        let mut buf = [0; 1024];
        let mut packet: Packet<1024> = Packet::new(&mut buf);
        packet.add_destination(d1.clone()).unwrap();
        packet.add_destination(d2.clone()).unwrap();

        let mut dests = packet.destination_iter();
        assert_eq!(d1, dests.next().unwrap());
        assert_eq!(d2, dests.next().unwrap());
        assert_eq!(None, dests.next());
    }

    #[test]
    fn route_clear() {
        let mut buf = [0; 1024];
        let mut p: Packet<1024> = Packet::new(&mut buf);
        p.add_identification(Identification::new(123, "call", 43).unwrap())
            .unwrap();
        let mut r = Route::new(8);
        r.push_internet().unwrap();
        p.add_route(r).unwrap();
        p.add_comment("This is a comment").unwrap();

        p.clear_route();

        assert_eq!(
            Identification::new(123, "call", 43).unwrap(),
            p.identification().unwrap()
        );
        assert_eq!(None, p.route());
        let mut buf = [0; 32];
        assert_eq!("This is a comment", p.comment(&mut buf).unwrap());
    }

    #[test]
    fn semi_e2e() {
        let comment = "Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.";

        let mut buf = [0; 2048];
        let mut packet = Packet::new(&mut buf);
        packet
            .add_identification(Identification {
                icon: 123,
                callsign: ArrayString::from("ABCXYZ_LONG_CALL").unwrap(),
                ssid: 43,
            })
            .unwrap();

        packet.add_comment(comment).unwrap();

        let res = packet.add_identification(Identification {
            icon: 456,
            callsign: ArrayString::from("NOPE").unwrap(),
            ssid: 0,
        });
        assert!(matches!(res, Err(EncodeError::DuplicateData)));

        let semi = packet.semi_encode().unwrap();

        let packet2 = Packet::semi_decode(semi).unwrap();
        assert_eq!(
            Identification {
                icon: 123,
                callsign: ArrayString::from("ABCXYZ_LONG_CALL").unwrap(),
                ssid: 43,
            },
            packet2.identification().unwrap()
        );

        let mut buf = [0; 1024];
        assert_eq!(comment, packet2.comment(&mut buf).unwrap());
    }
Stephen D's avatar
Stephen D committed

    #[test]
    fn full_e2e() {
        let comment = "Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.Hello world! This is a comment. It's long so that it needs to be split across more than one whisker.";

        let mut buf = [0; 4096];
        let mut packet = Packet::new(&mut buf);
Stephen D's avatar
Stephen D committed
        packet
            .add_identification(Identification {
                icon: 123,
                callsign: ArrayString::from("ABCXYZ_LONG_CALL").unwrap(),
                ssid: 43,
            })
            .unwrap();

        packet.add_comment(comment).unwrap();

        let res = packet.add_identification(Identification {
            icon: 456,
            callsign: ArrayString::from("NOPE").unwrap(),
            ssid: 0,
        });
        assert!(matches!(res, Err(EncodeError::DuplicateData)));

        let mut buf2 = [0; 4096];
        let mut fully = Buffer::new_empty(&mut buf2);
        packet.fully_encode(&mut fully).unwrap();
Stephen D's avatar
Stephen D committed

        fully[40] ^= 0x55;
        fully[844] ^= 0x7B;

        // exclude length
        let mut buf3 = [0; 8191];
        let packet2: Packet<8191> = Packet::fully_decode(&fully[2..], &mut buf3).unwrap();
Stephen D's avatar
Stephen D committed
        assert_eq!(
            Identification {
                icon: 123,
                callsign: ArrayString::from("ABCXYZ_LONG_CALL").unwrap(),
                ssid: 43,
            },
            packet2.identification().unwrap()
        );

        let mut buf = [0; 1024];
        assert_eq!(comment, packet2.comment(&mut buf).unwrap());
    }
Stephen D's avatar
Stephen D committed

    #[test]
    fn fully_decode_fuzz_tests() {
        let data = [
            112, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 74, 0, 0, 0, 0, 41, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 114, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10, 112, 0, 0, 0, 0, 0, 0, 2, 1, 0,
            0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 74, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39,
            114, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 145, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            59, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7,
            0, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 59, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 228, 0, 0, 0, 64, 0, 65, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 7, 0, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 1, 0, 0, 10, 118, 118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 64,
            0, 65, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 7, 0, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 1, 0, 0, 10, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 1, 2, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 0, 0, 118, 118, 118, 118,
            118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 96, 96,
        ];

        let mut buf = [0; 1024];
        let _ = Packet::<1024>::fully_decode(&data, &mut buf);
Stephen D's avatar
Stephen D committed
    }

    #[test]
    fn semi_decode_fuzz_tests() {
        let cases = [
Stephen D's avatar
Stephen D committed
            &[
                42, 64, 64, 64, 229, 40, 64, 64, 0, 0, 173, 173, 173, 173, 173, 173, 173, 173, 64,
                64, 0, 0, 173, 187, 187, 187, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
                173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 187, 187,
                187, 101, 157, 138, 74, 101, 157, 138, 74, 0, 0, 0, 0, 1, 126, 255, 255, 255, 187,
                187, 187, 187, 187, 187, 187, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
                173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 187, 101, 157, 138, 74, 101,
                157, 138, 106, 0, 0, 0, 0, 1, 126, 255, 255, 255, 0, 212, 0, 0, 0, 0, 1, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 173, 187, 187, 187, 101,
                157, 138, 74, 101, 157, 138, 74, 0, 0, 0, 0, 1, 126, 255, 255, 255, 0, 212, 0, 0,
                0, 0, 1, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 157, 138, 74, 0, 0, 0,
                0, 1, 126, 255, 255, 255, 0, 212, 0, 0, 0, 0, 1, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 187, 187, 187, 173, 187, 187, 64, 187, 101, 157, 138, 74, 101, 157,
                50, 138, 74, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
                255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
                255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
                255, 255, 255, 255, 255, 1, 126, 255, 255, 255, 0, 212, 0, 0, 0, 0, 1, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
                173, 173, 173, 173, 173, 173, 64, 64, 0, 0, 173, 173, 173, 173, 173, 173, 173, 173,
                173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
                173, 187, 187, 187, 101, 157, 138, 74, 101, 157, 138, 74, 0, 0, 0, 0, 1, 126, 255,
                255, 255, 0, 212, 0, 0, 0, 0, 1, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 173, 187, 187, 187, 101, 157, 138, 74, 101, 157, 138, 74, 0, 0, 0,
                0, 1, 126, 255, 255, 255, 0, 212, 0, 0, 0, 0, 1, 187, 187, 0, 0, 192, 192, 0, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 173, 173, 173, 173, 173, 173, 173,
                173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
                173, 64, 64, 0, 0, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
                173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 187, 187, 187, 101,
                157, 138, 74, 101, 157, 138, 74, 0, 0, 0, 0, 1, 126, 255, 255, 255, 0, 212, 0, 0,
                0, 0, 1, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 126,
            ][..],
            &[
                48, 5, 4, 255, 5, 5, 5, 5, 5, 5, 5, 37, 5, 7, 5, 5, 35, 5, 5, 5, 5, 4, 5, 7, 5, 5,
                5, 5, 5, 5, 5, 5, 11, 126, 3, 101, 5, 3, 3, 96, 192, 128, 192, 192,
            ][..],
        ];
Stephen D's avatar
Stephen D committed

        for data in cases {
            let mut buf = [0; 1024];
            let mut buf = Buffer::new_empty(&mut buf);
            buf.extend(data);
            let _ = Packet::<1024>::semi_decode(buf);
        }
Stephen D's avatar
Stephen D committed
    }

    #[test]
    fn decode_fuzz_tests() {
        let cases = [&[4, 0, 0, 0][..], &[4, 5, 0, 0, 0, 10, 255, 255, 0, 0][..]];
Stephen D's avatar
Stephen D committed

        for data in cases {
            let mut buf = [0; 1024];
            let mut buf = Buffer::new_empty(&mut buf);
            buf.extend(&data);
            let _ = Packet::<1024>::decode(buf);
        }
Stephen D's avatar
Stephen D committed
    }