use crate::error::{FoldError, Result};
pub const MAX_BOOT_FILE_BYTES: u64 = 512 * 1024 * 1024;
pub const MAX_DECOMPRESSED_BLOCK_BYTES: u64 = 16 * 1024 * 1024;
const _: () = assert!(MAX_DECOMPRESSED_BLOCK_BYTES < MAX_BOOT_FILE_BYTES);
pub fn checked_full_read_len(size: u64) -> Result<usize> {
checked_len(size, MAX_BOOT_FILE_BYTES)
}
pub fn checked_block_len(size: u64) -> Result<usize> {
checked_len(size, MAX_DECOMPRESSED_BLOCK_BYTES)
}
fn checked_len(size: u64, max: u64) -> Result<usize> {
if size > max {
return Err(FoldError::FileTooLarge { size, max });
}
usize::try_from(size).map_err(|_| FoldError::FileTooLarge { size, max })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn accepts_within_cap() {
assert_eq!(checked_full_read_len(0).unwrap(), 0);
assert_eq!(checked_full_read_len(1024).unwrap(), 1024);
assert_eq!(
checked_full_read_len(MAX_BOOT_FILE_BYTES).unwrap() as u64,
MAX_BOOT_FILE_BYTES
);
}
#[test]
fn rejects_over_cap() {
let e = checked_full_read_len(MAX_BOOT_FILE_BYTES + 1).unwrap_err();
assert!(matches!(e, FoldError::FileTooLarge { .. }));
assert_eq!(e.as_token(), "file_too_large");
}
#[test]
fn accepts_real_distro_initrd_over_256mib() {
let archiso = 238_531_280u64; let fedora = 275_797_175u64; assert!(checked_full_read_len(archiso).is_ok());
assert_eq!(checked_full_read_len(fedora).unwrap() as u64, fedora);
}
#[test]
fn block_cap_is_independent_and_smaller() {
assert!(checked_block_len(MAX_DECOMPRESSED_BLOCK_BYTES).is_ok());
assert!(checked_block_len(MAX_DECOMPRESSED_BLOCK_BYTES + 1).is_err());
}
#[test]
fn u64_that_overflows_usize_is_rejected_not_truncated() {
let huge = u64::MAX;
assert!(matches!(
checked_full_read_len(huge),
Err(FoldError::FileTooLarge { .. })
));
}
}