use core::fmt::Debug; use crc::{Crc, CRC_16_IBM_SDLC}; use crate::{ buffer::{Buffer, BufferOverflow}, error::{CommentError, DecodeError, EncodeError}, interleaver, ldpc, utf8, whisker::{ Arbitrary, Comment, Destination, Gps, Identification, Route, Timestamp, ValidatedWhiskerIter, Whisker, WhiskerIter, COMMENT_TYPE, }, 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); } } }; } /// N is the maximum packet size we can handle /// Panics if N >= 8191 pub struct Packet<'a, const N: usize> { buf: Buffer<'a, N>, } impl<'a, const N: usize> Packet<'a, N> { pub fn new(buf: &'a mut [u8; N]) -> Self { Self { buf: buf.into() } } pub fn clone_backing<'b>(&self, buf: &'b mut [u8; N]) -> Packet<'b, N> { Packet { buf: self.buf.clone_backing(buf), } } /// 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> { assert!(N <= 8191); // validate the data for w in WhiskerIter::new(&buf) { w?; } let comment_iter = WhiskerIter::new(&buf) .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); } Ok(Self { buf }) } pub fn encode(&self) -> &[u8] { &self.buf } /// Directly after the CRC block in The Pipeline pub fn semi_encode(mut self) -> Result<Buffer<'a, N>, (EncodeError, Self)> { let crc = X25.checksum(&self.buf).to_le_bytes(); let res: Result<(), BufferOverflow> = try_lock(&mut self.buf, |data| { data.try_push(crc[0])?; data.try_push(crc[1])?; Ok(()) }); match res { Ok(()) => Ok(self.buf), Err(_) => Err((EncodeError::CatsOverflow, self)), } } /// Directly after the CRC block in The Pipeline /// 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> { 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]); let crc_actual = X25.checksum(&buf); if crc_expected != crc_actual { return Err(DecodeError::CrcMismatch); } Self::decode(buf) } /// 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> { 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)?; Ok(()) } /// Decodes packet that was received over the air. /// Packet shouldn't have preamble, sync word, or data langth L. /// 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); 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); i += data.len(); } if !has_comment { return Err(CommentError::NoComment); } // 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; } } } } 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 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> { let len = buf.len(); match f(buf) { Ok(x) => Ok(x), Err(e) => { buf.truncate(len); Err(e) } } } #[cfg(test)] mod tests { use arrayvec::ArrayString; use super::*; #[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()); } #[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); 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(); 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(); 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()); } #[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); } #[test] fn semi_decode_fuzz_tests() { let cases = [ &[ 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, ][..], ]; 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); } } #[test] fn decode_fuzz_tests() { let cases = [&[4, 0, 0, 0][..], &[4, 5, 0, 0, 0, 10, 255, 255, 0, 0][..]]; 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); } } }