use crate::{constants, BlockType};
pub fn fit_order(size: usize) -> usize {
(std::mem::size_of::<usize>() * 8 - (size - 1).leading_zeros() as usize)
.saturating_sub(constants::MIN_ORDER_SHIFT)
}
pub fn order_to_size(order: u8) -> usize {
constants::MIN_ORDER_SIZE << order
}
pub fn block_size_for_payload(payload_size: usize) -> usize {
(payload_size + constants::HEADER_SIZE_BYTES)
.clamp(constants::MIN_ORDER_SIZE, constants::MAX_ORDER_SIZE)
}
pub fn payload_size_for_order(order: u8) -> usize {
order_to_size(order) - constants::HEADER_SIZE_BYTES
}
pub fn array_capacity(order: u8, entry_type: BlockType) -> Option<usize> {
entry_type.array_element_size().map(|size| {
(order_to_size(order)
- constants::HEADER_SIZE_BYTES
- constants::ARRAY_PAYLOAD_METADATA_SIZE_BYTES)
/ size
})
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn fit_order_test() {
assert_eq!(0, fit_order(1));
assert_eq!(0, fit_order(16));
assert_eq!(1, fit_order(17));
assert_eq!(2, fit_order(33));
assert_eq!(7, fit_order(2048));
}
#[test]
fn order_to_size_test() {
assert_eq!(16, order_to_size(0));
assert_eq!(32, order_to_size(1));
assert_eq!(64, order_to_size(2));
assert_eq!(128, order_to_size(3));
assert_eq!(256, order_to_size(4));
assert_eq!(512, order_to_size(5));
assert_eq!(1024, order_to_size(6));
assert_eq!(2048, order_to_size(7));
}
#[test]
fn fit_payload_test() {
for payload_size in 0..500 {
let block_size = block_size_for_payload(payload_size);
let order = fit_order(block_size) as u8;
let payload_max = payload_size_for_order(order);
assert!(
payload_size <= payload_max,
"Needed {} bytes for a payload, but only got {}; block size {}, order {}",
payload_size,
payload_max,
block_size,
order
);
}
}
#[test]
fn array_capacity_numeric() {
assert_eq!(2, array_capacity(1, BlockType::IntValue).expect("get size"));
assert_eq!(2 + 4, array_capacity(2, BlockType::IntValue).expect("get size"));
assert_eq!(2 + 4 + 8, array_capacity(3, BlockType::IntValue).expect("get size"));
assert_eq!(2 + 4 + 8 + 16, array_capacity(4, BlockType::IntValue).expect("get size"));
assert_eq!(2 + 4 + 8 + 16 + 32, array_capacity(5, BlockType::IntValue).expect("get size"));
assert_eq!(
2 + 4 + 8 + 16 + 32 + 64,
array_capacity(6, BlockType::IntValue).expect("get size")
);
assert_eq!(
2 + 4 + 8 + 16 + 32 + 64 + 128,
array_capacity(7, BlockType::IntValue).expect("get size")
);
}
#[test]
fn array_capacity_string_reference() {
assert_eq!(4, array_capacity(1, BlockType::StringReference).expect("get size"));
assert_eq!(4 + 8, array_capacity(2, BlockType::StringReference).expect("get size"));
assert_eq!(4 + 8 + 16, array_capacity(3, BlockType::StringReference).expect("get size"));
assert_eq!(
4 + 8 + 16 + 32,
array_capacity(4, BlockType::StringReference).expect("get size")
);
assert_eq!(
4 + 8 + 16 + 32 + 64,
array_capacity(5, BlockType::StringReference).expect("get size")
);
assert_eq!(
4 + 8 + 16 + 32 + 64 + 128,
array_capacity(6, BlockType::StringReference).expect("get size")
);
assert_eq!(
4 + 8 + 16 + 32 + 64 + 128 + 256,
array_capacity(7, BlockType::StringReference).expect("get size")
);
}
}