1pub fn round_up<T: Into<U>, U: Copy + num_traits::PrimInt>(offset: U, block_size: T) -> Option<U> {
11 let block_size = block_size.into();
12 #[allow(clippy::eq_op)]
13 let one = block_size / block_size;
14 Some(round_down(offset.checked_add(&(block_size - one))?, block_size))
15}
16
17pub fn round_down<
19 T: Into<U>,
20 U: Copy + std::ops::Rem<U, Output = U> + std::ops::Sub<U, Output = U>,
21>(
22 offset: U,
23 block_size: T,
24) -> U {
25 let block_size = block_size.into();
26 offset - offset % block_size
27}
28
29pub fn round_div(numerator: u64, denominator: u64) -> Option<u64> {
33 numerator.checked_add(denominator / 2)?.checked_div(denominator)
34}
35
36pub fn how_many<T: Into<u64>>(value: u64, item_size: T) -> u64 {
41 let item_size = item_size.into();
42 let items = value / item_size;
43 let remainder = value % item_size;
44 if remainder != 0 { items + 1 } else { items }
45}
46
47#[cfg(test)]
48mod tests {
49 use crate::round::{how_many, round_div};
50
51 #[test]
52 fn test_how_many() {
53 assert_eq!(how_many(0, 3u64), 0);
54 assert_eq!(how_many(1, 3u64), 1);
55 assert_eq!(how_many(2, 3u64), 1);
56 assert_eq!(how_many(3, 3u64), 1);
57 assert_eq!(how_many(4, 3u64), 2);
58 assert_eq!(how_many(5, 3u64), 2);
59 assert_eq!(how_many(6, 3u64), 2);
60
61 assert_eq!(how_many(17u64, 3u8), 6u64);
62
63 assert_eq!(how_many(u64::MAX, 4096u32), u64::MAX / 4096 + 1);
64 }
65
66 #[test]
67 fn test_round_div() {
68 assert_eq!(round_div(9, 4), Some(2));
69 assert_eq!(round_div(10, 4), Some(3));
70 assert_eq!(round_div(11, 4), Some(3));
71 assert_eq!(round_div(12, 4), Some(3));
72 assert_eq!(round_div(13, 4), Some(3));
73 assert_eq!(round_div(14, 4), Some(4));
74 assert_eq!(round_div(0, 1), Some(0));
75 assert_eq!(round_div(100, 0), None);
76 assert_eq!(round_div(u64::MAX, 2), None);
77 }
78}