use std::io::{self, Read};
pub(crate) trait ByteLimit {
const MAX_BYTES: u64;
}
#[expect(dead_code)]
struct SmallByteLimit;
#[expect(dead_code)]
struct MediumByteLimit;
#[derive(Default)]
pub(crate) struct DefaultByteLimit;
#[expect(dead_code)]
pub(crate) struct CustomByteLimit<const N: usize>;
const ONE_KI_B: u64 = 1024; #[expect(dead_code)]
const FIVE_HUNDRED_KI_B: u64 = 500 * ONE_KI_B; const ONE_MI_B: u64 = 1024 * ONE_KI_B;
impl ByteLimit for SmallByteLimit {
const MAX_BYTES: u64 = FIVE_HUNDRED_KI_B;
}
impl ByteLimit for MediumByteLimit {
const MAX_BYTES: u64 = ONE_MI_B;
}
impl ByteLimit for DefaultByteLimit {
const MAX_BYTES: u64 = ONE_MI_B;
}
pub(crate) fn with_limited_reader<R, F, O, E, M>(
mut reader: R,
byte_limit: u64,
f: F,
map_io_error: M,
) -> Result<O, E>
where
R: Read,
F: FnOnce(&mut dyn Read) -> Result<O, E>,
M: FnOnce(io::Error) -> E,
{
let mut limited = reader.by_ref().take(byte_limit);
let output = f(&mut limited)?;
drop(limited);
let mut extra = [0u8; 1];
match reader.read(&mut extra) {
Ok(0) => Ok(output),
Ok(_) => Err(map_io_error(io::Error::new(
io::ErrorKind::Other,
"input exceeded maximum byte limit",
))),
Err(e) => Err(map_io_error(e)),
}
}