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 {
45 items + 1
46 } else {
47 items
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use crate::round::{how_many, round_div};
54
55 #[test]
56 fn test_how_many() {
57 assert_eq!(how_many(0, 3u64), 0);
58 assert_eq!(how_many(1, 3u64), 1);
59 assert_eq!(how_many(2, 3u64), 1);
60 assert_eq!(how_many(3, 3u64), 1);
61 assert_eq!(how_many(4, 3u64), 2);
62 assert_eq!(how_many(5, 3u64), 2);
63 assert_eq!(how_many(6, 3u64), 2);
64
65 assert_eq!(how_many(17u64, 3u8), 6u64);
66
67 assert_eq!(how_many(u64::MAX, 4096u32), u64::MAX / 4096 + 1);
68 }
69
70 #[test]
71 fn test_round_div() {
72 assert_eq!(round_div(9, 4), Some(2));
73 assert_eq!(round_div(10, 4), Some(3));
74 assert_eq!(round_div(11, 4), Some(3));
75 assert_eq!(round_div(12, 4), Some(3));
76 assert_eq!(round_div(13, 4), Some(3));
77 assert_eq!(round_div(14, 4), Some(4));
78 assert_eq!(round_div(0, 1), Some(0));
79 assert_eq!(round_div(100, 0), None);
80 assert_eq!(round_div(u64::MAX, 2), None);
81 }
82}