#![allow(clippy::pedantic, missing_docs)]
use cobs_codec_rs::{cobs, cobsr};
struct Rng(u64);
impl Rng {
fn new(seed: u64) -> Self {
Self(seed)
}
fn next(&mut self) -> u64 {
let mut x = self.0;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.0 = x;
x
}
fn byte(&mut self) -> u8 {
(self.next() & 0xFF) as u8
}
fn stress_byte(&mut self) -> u8 {
match self.next() % 4 {
0 => 0x00,
1 => 0xFF,
2 => (self.next() % 6) as u8,
_ => self.byte(),
}
}
fn stress_bytes(&mut self, len: usize) -> Vec<u8> {
(0..len).map(|_| self.stress_byte()).collect()
}
}
#[test]
fn decode_is_total_on_arbitrary_input() {
let mut rng = Rng::new(0xF0FA_D00D_1111_2222);
let mut scratch = vec![0u8; 1024];
for _ in 0..200_000 {
let len = (rng.next() as usize) % 512;
let input = rng.stress_bytes(len);
let _ = cobsr::decode(&input, &mut scratch);
let s = rng.byte();
let _ = cobs::decode_with_sentinel(&input, &mut scratch, s);
let slice = cobs::decode(&input, &mut scratch);
let mut buf = input.clone();
let in_place = cobs::decode_in_place(&mut buf);
match (slice, in_place) {
(Ok(m), Ok(n)) => {
assert_eq!(m, n, "length mismatch on {input:02x?}");
assert_eq!(&scratch[..m], &buf[..n], "byte mismatch on {input:02x?}");
}
(Err(_), Err(_)) => {}
(a, b) => panic!("slice/in-place disagree on {input:02x?}: {a:?} vs {b:?}"),
}
}
}
#[test]
fn encode_decode_round_trips_arbitrary_payloads() {
let mut rng = Rng::new(0xC0FF_EE00_3333_4444);
let mut enc = vec![0u8; 8192];
let mut dec = vec![0u8; 8192];
for _ in 0..100_000 {
let len = (rng.next() as usize) % 700;
let src = rng.stress_bytes(len);
let n = cobs::encode(&src, &mut enc);
assert!(!enc[..n].contains(&0), "COBS output contains 0x00");
let m = cobs::decode(&enc[..n], &mut dec).unwrap();
assert_eq!(&dec[..m], &src[..]);
let n = cobsr::encode(&src, &mut enc);
assert!(!enc[..n].contains(&0), "COBS/R output contains 0x00");
let m = cobsr::decode(&enc[..n], &mut dec).unwrap();
assert_eq!(&dec[..m], &src[..]);
let s = rng.byte();
let n = cobs::encode_with_sentinel(&src, &mut enc, s);
if s != 0 {
assert!(!enc[..n].contains(&s), "sentinel byte {s:#04x} in output");
}
let m = cobs::decode_with_sentinel(&enc[..n], &mut dec, s).unwrap();
assert_eq!(&dec[..m], &src[..]);
}
}