use core::fmt::Debug;
use crc::{Crc, CRC_16_IBM_SDLC};
use labrador_ldpc::decoder::DecodeFrom;
use crate::{
buffer::{Buffer, BufferOverflow},
error::{CommentError, DecodeError, DigipeatError, EncodeError, PacketRouteAppendError},
identity::Identity,
interleaver, ldpc, utf8,
whisker::{
Arbitrary, Comment, Destination, Gps, Identification, NodeInfo, PastHop, Route, RouteHop,
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:snake:lower>](&self) -> Option<$t> {
self.iter().find_map(|w| match w {
Whisker::$t(x) => Some(x),
_ => None,
})
}
pub fn [<add_ $t:snake:lower>](&mut self, w: $t) -> Result<(), EncodeError> {
if self.[<$t:snake: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:snake:upper _TYPE>]).ok().ok_or(EncodeError::CatsOverflow)?;
data.try_extend_from_slice(out).ok().ok_or(EncodeError::CatsOverflow)?;
Ok(())
})?;
Ok(())
}
pub fn [<clear_ $t:snake:lower>](&mut self) {
self.clear_by_type(crate::whisker::[<$t:snake: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<const M: usize>(self, out: &mut Buffer<M>) -> 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 `data`
/// `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)
}
/// Expects soft bits in `data`. Bits should be LLR, with positive numbers more likely to be 0.
/// Returns `DecodeError::Overflow` if `M` is less than `data.len()`.
pub fn fully_decode_soft<const M: usize, T: DecodeFrom>(
data: &mut [T],
buf: &'a mut [u8; N],
) -> Result<Self, DecodeError> {
let mut out = [T::zero(); M];
let mut out = Buffer::new_empty(&mut out);
interleaver::uninterleave_soft(data, &mut out).map_err(|_| DecodeError::Overflow)?;
let mut buf = Buffer::new_empty(buf);
ldpc::decode_soft(&mut out, &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);
uniq_whisker!(NodeInfo);
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);
}
/// Given the callsign and ssid of a node, should it digipeat this packet?
/// Takes into account things such as if we've digipeated it already, the max hops, etc.
pub fn should_digipeat(&self, identity: Identity) -> Result<(), DigipeatError> {
let route = match self.route() {
Some(x) => x,
None => {
return Err(DigipeatError::NoRoute);
}
};
if let Some(ident) = self.identification() {
if &ident.callsign == identity.callsign() && ident.ssid == identity.ssid() {
return Err(DigipeatError::Us);
}
}
let max_hops: usize = route.max_hops.into();
let cur_hops = route
.iter()
.filter(|r| match r {
RouteHop::Internet => false,
RouteHop::Past(_) => true,
RouteHop::Future(_) => false,
})
.count();
if max_hops <= cur_hops {
return Err(DigipeatError::MaxHops);
}
let already_digipeated = route.iter().any(|r| match r {
RouteHop::Internet => false,
RouteHop::Past(past_hop) => past_hop.identity() == identity,
RouteHop::Future(_) => false,
});
if already_digipeated {
return Err(DigipeatError::AlreadyDigipeated);
}
let next_node = route.iter().find_map(|r| match r {
RouteHop::Future(x) => Some(x),
_ => None,
});
match next_node {
Some(ident) if ident != identity => Err(DigipeatError::SetDestiny),
_ => Ok(()),
}
}
/// Note that if this fails due to a CATS overflow, it will wipe the route off of the packet
pub fn append_to_route(
&mut self,
callsign: &str,
ssid: u8,
rssi: Option<f64>,
) -> Result<(), PacketRouteAppendError> {
let mut route = self.route().ok_or(PacketRouteAppendError::NoRouteWhisker)?;
route
.append_hop(PastHop::new(Identity::new(callsign, ssid), rssi))
.map_err(|error| PacketRouteAppendError::Route { error })?;
self.clear_route();
self.add_route(route)
.map_err(|_| PacketRouteAppendError::PacketOverflow)?;
Ok(())
}
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<const N: usize> Debug for Packet<'_, 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 super::*;
use crate::whisker::NodeInfoBuilder;
use crate::{soft_bit::FromHardBit, whisker::AckData};
use arrayvec::ArrayString;
use bitvec::{order::Msb0, view::BitView};
#[test]
fn dest() {
let d1 = Destination::new("CALL1", 23, Some(AckData::new(7, false))).unwrap();
let d2 = Destination::new("CALL2", 2, Some(AckData::new(23, true))).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("call", 43, 123).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("call", 43, 123).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 full_e2e_soft_decode() {
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;
let mut soft = [0.0; 8191 * 8];
let mut soft = Buffer::new_empty(&mut soft);
for b in fully.view_bits::<Msb0>().iter() {
soft.push(f32::from_hard_bit(*b));
}
let soft = &mut soft[16..];
let mut buf3 = [0; 8191];
// exclude length
let packet2: Packet<8191> =
Packet::fully_decode_soft::<{ 8191 * 8 }, _>(soft, &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 node_info_e2e() {
let mut buf = [0; 4096];
let mut packet = Packet::new(&mut buf);
packet
.add_node_info(
NodeInfoBuilder::default()
.hardware_id(0xBEEF)
.software_id(0xBC)
.uptime(2304)
.antenna_height(5)
.antenna_gain(3.0)
.tx_power(30.0)
.voltage(12.6)
.xcvr_temperature(-15)
.battery_charge(65.0)
.build(),
)
.unwrap();
let mut buf2 = [0; 4096];
let mut encoded = Buffer::new_empty(&mut buf2);
packet.fully_encode(&mut encoded).unwrap();
let mut buf3 = [0; 4096];
let packet2 = Packet::fully_decode(&encoded[2..], &mut buf3).unwrap();
let node_info = packet2.node_info().unwrap();
assert_eq!(0xBEEF, node_info.hardware_id().unwrap());
assert_eq!(0xBC, node_info.software_id().unwrap());
assert_eq!(2304, node_info.uptime().unwrap());
assert_eq!(5, node_info.antenna_height().unwrap());
assert_eq!(3.0, node_info.antenna_gain().unwrap());
assert_eq!(30.0, node_info.tx_power().unwrap());
assert_eq!(12.6, node_info.voltage().unwrap());
assert_eq!(-15, node_info.xcvr_temperature().unwrap());
assert_eq!(64.70588235294117, node_info.battery_charge().unwrap());
}
#[test]
fn node_info_e2e_some_unpopulated() {
let mut buf = [0; 4096];
let mut packet = Packet::new(&mut buf);
packet
.add_node_info(
NodeInfoBuilder::default()
.software_id(0xBC)
.uptime(2304)
.antenna_gain(3.0)
.voltage(12.6)
.xcvr_temperature(-15)
.build(),
)
.unwrap();
let mut buf2 = [0; 4096];
let mut encoded = Buffer::new_empty(&mut buf2);
packet.fully_encode(&mut encoded).unwrap();
let mut buf3 = [0; 4096];
let packet2 = Packet::fully_decode(&encoded[2..], &mut buf3).unwrap();
let node_info = packet2.node_info().unwrap();
assert_eq!(None, node_info.hardware_id());
assert_eq!(0xBC, node_info.software_id().unwrap());
assert_eq!(2304, node_info.uptime().unwrap());
assert_eq!(None, node_info.antenna_height());
assert_eq!(3.0, node_info.antenna_gain().unwrap());
assert_eq!(None, node_info.tx_power());
assert_eq!(12.6, node_info.voltage().unwrap());
assert_eq!(-15, node_info.xcvr_temperature().unwrap());
assert_eq!(None, node_info.battery_charge());
}
#[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);
}
}
#[test]
fn fully_decode_soft_fuzz_tests() {
// When adding to this, don't forget to do the u8 -> i8 conversion
let cases = [
&mut [
-39, -39, -39, -118, -58, -58, -58, -58, -89, -39, -118, -58, -58, -58, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, -58, -58,
127, 81, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, -86, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, -58, -58, 127,
81, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, -58, -58, 127, 81, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, -128, -128,
][..],
&mut [
-73, -73, -73, -73, -75, -76, -73, -73, -73, -73, -73, -73, -73, -73, 73, 72, 72,
72, 72, 72, 72, 62, -73, -118, 120, 127, 127, 121, 127, 112, 127, 127,
],
];
for data in cases {
let mut buf = [0; 1024];
let _ = Packet::<1024>::fully_decode_soft::<8192, i8>(data, &mut buf);
}
}
}