use crate::error::{ArrayError, ArrayResult};
pub const MAX_CELLS_PER_TILE: usize = 8_000_000;
pub const MAX_AXES_PER_TILE: usize = 1_024;
pub const MAX_ATTRS_PER_TILE: usize = 1_024;
pub const MAX_DICT_CARDINALITY: usize = 8_000_000;
pub const MAX_RLE_RUNS: usize = 8_000_000;
pub const MAX_RLE_RUN_LEN: usize = MAX_CELLS_PER_TILE;
pub const MAX_COLUMN_ENTRIES: usize = MAX_CELLS_PER_TILE;
pub fn check_decoded_size(value: usize, cap: usize, what: &str) -> ArrayResult<()> {
checked_capacity(value, cap, 0, 0, what).map(|_| ())
}
pub fn checked_capacity(
value: usize,
cap: usize,
remaining_bytes: usize,
min_encoded_bytes: usize,
what: &str,
) -> ArrayResult<usize> {
if value > cap {
return Err(ArrayError::SegmentCorruption {
detail: format!(
"decoded {what} = {value} exceeds hard cap {cap} (segment likely corrupt)"
),
});
}
let minimum_bytes =
value
.checked_mul(min_encoded_bytes)
.ok_or_else(|| ArrayError::SegmentCorruption {
detail: format!("decoded {what} minimum encoded size overflows"),
})?;
if minimum_bytes > remaining_bytes {
return Err(ArrayError::SegmentCorruption {
detail: format!(
"decoded {what} requires at least {minimum_bytes} encoded bytes, only {remaining_bytes} remain"
),
});
}
Ok(value)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn checked_capacity_rejects_count_without_minimum_encoded_bytes() {
assert!(checked_capacity(2, 8, 7, 4, "test entries").is_err());
}
#[test]
fn checked_capacity_rejects_count_over_hard_cap() {
assert!(checked_capacity(9, 8, 36, 4, "test entries").is_err());
}
#[test]
fn checked_capacity_returns_validated_count() {
assert_eq!(checked_capacity(2, 8, 8, 4, "test entries").unwrap(), 2);
}
}