use super::DecodeErr;
#[cfg(any(
target_pointer_width = "16",
target_pointer_width = "32",
target_pointer_width = "64",
))]
use super::MAX_ENCODE_INPUT_LEN;
#[cfg(feature = "alloc")]
use alloc::{borrow::ToOwned as _, string::String, vec};
use core::fmt::{self, Write};
#[cfg(any(
target_pointer_width = "16",
target_pointer_width = "32",
target_pointer_width = "64",
))]
use rand::{RngExt as _, rngs::SmallRng};
#[expect(
clippy::as_conversions,
clippy::cast_possible_truncation,
reason = "comment justifies correctness"
)]
#[cfg(any(
target_pointer_width = "16",
target_pointer_width = "32",
target_pointer_width = "64",
))]
#[ignore = "slow"]
#[test]
fn encode_decode_len() {
assert_eq!(MAX_ENCODE_INPUT_LEN, 3 * (usize::MAX.div_ceil(4)) - 1);
let mut rng = rand::make_rng::<SmallRng>();
for _ in 0u32..10_000_000 {
#[cfg(target_pointer_width = "16")]
let len = rng.random::<u16>() as usize;
#[cfg(target_pointer_width = "32")]
let len = rng.random::<u32>() as usize;
#[cfg(target_pointer_width = "64")]
let len = rng.random::<u64>() as usize;
if len <= MAX_ENCODE_INPUT_LEN {
assert_eq!(
super::encode_len_checked(len).map(super::decode_len),
Some(Some(len))
);
} else {
assert!(super::encode_len_checked(len).is_none());
}
}
for i in 0..1025 {
assert_eq!(
super::encode_len_checked(i).map(super::decode_len),
Some(Some(i))
);
}
#[cfg(target_pointer_width = "16")]
for i in MAX_ENCODE_INPUT_LEN + 1.. {
assert!(super::encode_len_checked(i).is_none());
}
#[cfg(not(target_pointer_width = "16"))]
for i in MAX_ENCODE_INPUT_LEN + 1..MAX_ENCODE_INPUT_LEN + 1_000_000 {
assert!(super::encode_len_checked(i).is_none());
}
assert!(super::encode_len_checked(usize::MAX).is_none());
assert_eq!(
super::encode_len_checked(MAX_ENCODE_INPUT_LEN),
Some(usize::MAX)
);
for _ in 0u32..10_000_000 {
#[cfg(target_pointer_width = "16")]
let len = rng.random::<u16>() as usize;
#[cfg(target_pointer_width = "32")]
let len = rng.random::<u32>() as usize;
#[cfg(target_pointer_width = "64")]
let len = rng.random::<u64>() as usize;
if len & 3 == 1 {
assert!(super::decode_len(len).is_none());
} else {
assert_eq!(
super::decode_len(len).map(super::encode_len_checked),
Some(Some(len))
);
}
}
for i in 0..1025 {
if i & 3 == 1 {
assert!(super::decode_len(i).is_none());
} else {
assert_eq!(
super::decode_len(i).map(super::encode_len_checked),
Some(Some(i))
);
}
}
#[cfg(target_pointer_width = "16")]
for i in 0..=usize::MAX {
if i & 3 == 1 {
assert!(super::decode_len(i).is_none());
} else {
assert_eq!(
super::decode_len(i).map(super::encode_len_checked),
Some(Some(i))
);
}
}
#[cfg(not(target_pointer_width = "16"))]
for i in usize::MAX - 1_000_000..=usize::MAX {
if i & 3 == 1 {
assert!(super::decode_len(i).is_none());
} else {
assert_eq!(
super::decode_len(i).map(super::encode_len_checked),
Some(Some(i))
);
}
}
assert_eq!(super::decode_len(usize::MAX), Some(MAX_ENCODE_INPUT_LEN));
}
#[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
#[cfg(feature = "alloc")]
#[test]
fn encode_write() {
let input = [9; 8192];
let mut buffer = String::with_capacity(super::encode_len(input.len()));
let cap = buffer.capacity();
let mut write_len;
for len in 0..input.len() {
write_len = super::encode_len(len);
match write_len.checked_add(buffer.len()) {
None => {
buffer.clear();
assert_eq!(super::encode_write(&input[..len], &mut buffer), Ok(()));
assert_eq!(buffer.len(), write_len);
}
Some(l) => {
if l > cap {
buffer.clear();
assert_eq!(super::encode_write(&input[..len], &mut buffer), Ok(()));
assert_eq!(buffer.len(), write_len);
} else {
assert_eq!(super::encode_write(&input[..len], &mut buffer), Ok(()));
assert_eq!(buffer.len(), l);
}
}
}
assert!(
buffer
.as_bytes()
.iter()
.all(|b| { matches!(*b, b'C' | b'J' | b'Q' | b'k') })
);
}
}
#[cfg(feature = "alloc")]
#[test]
fn try_encode() {
assert_eq!(super::try_encode(&[0]), Ok("AA".to_owned()));
}
#[cfg(feature = "alloc")]
#[test]
fn encode() {
assert_eq!(super::encode(&[0]), "AA".to_owned());
}
#[cfg(feature = "alloc")]
#[test]
fn try_encode_append() {
let mut val = "Hi".to_owned();
assert_eq!(
super::try_encode_append(&[0], &mut val),
Ok("AA".to_owned().as_mut_str())
);
assert_eq!(val, "HiAA");
}
#[cfg(feature = "alloc")]
#[test]
fn encode_append() {
let mut val = "Hi".to_owned();
assert_eq!(
super::encode_append(&[0], &mut val),
"AA".to_owned().as_mut_str()
);
assert_eq!(val, "HiAA");
}
#[cfg(feature = "alloc")]
#[test]
fn try_encode_append_only() {
let mut val = "Hi".to_owned();
assert_eq!(super::try_encode_append_only(&[0], &mut val), Ok(()));
assert_eq!(val, "HiAA");
}
#[cfg(feature = "alloc")]
#[test]
fn encode_append_only() {
let mut val = "Hi".to_owned();
super::encode_append_only(&[0], &mut val);
assert_eq!(val, "HiAA");
}
#[test]
fn decode_buffer() {
assert_eq!(
super::decode_buffer(b"AA", &mut [0]),
Ok([0].as_mut_slice())
);
assert_eq!(
super::decode_buffer(b"AA", &mut []),
Err(DecodeErr::BufferLen)
);
}
#[cfg(feature = "alloc")]
#[test]
fn decode() {
assert_eq!(super::decode(b"AA"), Ok(vec![0]));
}
#[test]
fn validate_encoded_data() {
assert_eq!(super::validate_encoded_data(b"AA"), Ok(()));
}
#[test]
fn encode_buffer_exact() {
let mut output = [0; 2];
super::encode_buffer_exact(&[0], &mut output);
assert_eq!(output, *b"AA");
}
#[test]
fn decode_buffer_exact() {
let mut output = [1];
assert_eq!(super::decode_buffer_exact(b"AA", &mut output), Ok(()));
assert_eq!(output, [0]);
}
#[test]
fn encode_write_core() {
struct Writer<'a>(&'a mut [u8]);
impl Write for Writer<'_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0.get_mut(..s.len()).ok_or(fmt::Error).map(|bytes| {
bytes.copy_from_slice(s.as_bytes());
})
}
}
let mut writer = Writer(&mut [0, 0, 1]);
assert_eq!(super::encode_write(&[0], &mut writer), Ok(()));
assert_eq!(writer.0, b"AA\x01");
assert_eq!(
super::encode_write(&[0, 0, 0], &mut writer),
Err(fmt::Error)
);
}