const _: () = assert!(usize::BITS <= u64::BITS);
#[inline]
pub(crate) const fn len_u64(value: usize) -> u64 {
value as u64
}
const _: () = assert!(usize::BITS >= 32);
#[inline]
pub(crate) const fn usize_from_u32(value: u32) -> usize {
value as usize
}
#[inline]
pub(crate) fn try_convert<T: TryFrom<U>, U, E>(value: U, error: E) -> Result<T, E> {
T::try_from(value).map_err(|_| error)
}
#[inline]
pub(crate) fn checked_read_count(
read: usize,
requested: usize,
reason: &'static str,
) -> crate::Result<usize> {
if read > requested {
return Err(crate::Error::invalid(reason));
}
Ok(read)
}
#[inline]
pub(crate) fn reserve_exact<T, E>(vec: &mut Vec<T>, additional: usize, error: E) -> Result<(), E> {
vec.try_reserve_exact(additional).map_err(|_| error)
}
#[inline]
pub(crate) fn reserve<T, E>(vec: &mut Vec<T>, additional: usize, error: E) -> Result<(), E> {
vec.try_reserve(additional).map_err(|_| error)
}
pub(crate) fn push_bounded<T>(
items: &mut Vec<T>,
item: T,
max_bytes: u64,
resource: &'static str,
) -> crate::Result<()> {
let next = items.len().checked_add(1).ok_or(crate::Error::invalid(
"PDF index length overflows address space",
))?;
if next > items.capacity() {
let target = items.capacity().saturating_mul(2).max(4).max(next);
let attempted = target
.checked_mul(size_of::<T>())
.ok_or(crate::Error::invalid(
"PDF index allocation overflows address space",
))?;
let limit = crate::Error::limit(resource, max_bytes, len_u64(attempted));
if len_u64(attempted) > max_bytes {
return Err(limit);
}
reserve_exact(items, target - items.len(), limit)?;
}
items.push(item);
Ok(())
}
#[cfg(test)]
mod tests;