1use off64::u8;
2
3#[derive(Clone, Copy)]
13pub struct TailPageSizes(u64, u64);
14
15impl TailPageSizes {
16 pub fn new() -> Self {
17 Self(0, 0)
18 }
19
20 fn shard_get_len(shard: u64) -> u8 {
21 u8!((shard & (0b1111 << 60)) >> 60)
22 }
23
24 fn shard_set_len(shard: &mut u64, len: u8) {
25 assert!(len <= 12);
26 *shard &= !(0b1111 << 60);
27 *shard |= u64::from(len) << 60;
28 }
29
30 fn shard_get(shard: u64, idx: u8) -> u8 {
31 assert!(idx < 12);
32 let shift = idx * 5;
33 u8!((shard & (0b11111 << shift)) >> shift)
34 }
35
36 fn shard_set(shard: &mut u64, idx: u8, val: u8) {
37 assert!(val < (1 << 5));
38 let shift = idx * 5;
39 *shard &= !(0b11111 << shift);
40 *shard |= u64::from(val) << shift;
41 }
42
43 pub fn len(&self) -> u8 {
44 Self::shard_get_len(self.0) + Self::shard_get_len(self.1)
45 }
46
47 pub fn get(&self, idx: u8) -> Option<u8> {
48 if idx >= self.len() {
49 return None;
50 };
51 Some(if idx < 12 {
52 Self::shard_get(self.0, idx)
53 } else {
54 Self::shard_get(self.1, idx - 12)
55 })
56 }
57
58 pub fn push(&mut self, pow2: u8) {
59 let idx = self.len();
60 if idx < 12 {
61 Self::shard_set(&mut self.0, idx, pow2);
62 Self::shard_set_len(&mut self.0, idx + 1);
63 } else {
64 Self::shard_set(&mut self.1, idx - 12, pow2);
65 Self::shard_set_len(&mut self.1, idx - 12 + 1);
66 };
67 }
68}
69
70impl IntoIterator for TailPageSizes {
71 type IntoIter = TailPageSizesIter;
72 type Item = (u8, u8);
73
74 fn into_iter(self) -> Self::IntoIter {
75 TailPageSizesIter(self, 0)
76 }
77}
78
79pub struct TailPageSizesIter(TailPageSizes, u8);
81
82impl Iterator for TailPageSizesIter {
83 type Item = (u8, u8);
84
85 fn next(&mut self) -> Option<Self::Item> {
86 let idx = self.1;
87 let entry = self.0.get(idx)?;
88 self.1 += 1;
89 Some((idx, entry))
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::TailPageSizes;
96 use itertools::Itertools;
97
98 #[test]
99 fn test_tail_page_sizes() {
100 let mut tail = TailPageSizes::new();
101 assert_eq!(tail.into_iter().collect_vec(), vec![]);
103
104 tail.push(5);
105 assert_eq!(tail.into_iter().collect_vec(), vec![(0, 5)]);
106
107 tail.push(3);
108 assert_eq!(tail.into_iter().collect_vec(), vec![(0, 5), (1, 3)]);
109
110 tail.push(8);
111 assert_eq!(tail.into_iter().collect_vec(), vec![(0, 5), (1, 3), (2, 8)]);
112 assert_eq!(tail.get(1), Some(3));
113 assert_eq!(tail.get(3), None);
114
115 tail.push(9);
116 assert_eq!(tail.into_iter().collect_vec(), vec![
117 (0, 5),
118 (1, 3),
119 (2, 8),
120 (3, 9),
121 ]);
122 assert_eq!(tail.len(), 4);
123 assert_eq!(tail.get(0), Some(5));
124 assert_eq!(tail.get(4), None);
125
126 tail.push(4);
127 assert_eq!(tail.into_iter().collect_vec(), vec![
128 (0, 5),
129 (1, 3),
130 (2, 8),
131 (3, 9),
132 (4, 4)
133 ]);
134 assert_eq!(tail.len(), 5);
135 assert_eq!(tail.get(3), Some(9));
136 assert_eq!(tail.get(5), None);
137
138 tail.push(11);
139 assert_eq!(tail.into_iter().collect_vec(), vec![
140 (0, 5),
141 (1, 3),
142 (2, 8),
143 (3, 9),
144 (4, 4),
145 (5, 11),
146 ]);
147 assert_eq!(tail.len(), 6);
148 assert_eq!(tail.get(0), Some(5));
149 assert_eq!(tail.get(4), Some(4));
150 assert_eq!(tail.get(5), Some(11));
151 assert_eq!(tail.get(6), None);
152
153 tail.push(14);
154 assert_eq!(tail.into_iter().collect_vec(), vec![
155 (0, 5),
156 (1, 3),
157 (2, 8),
158 (3, 9),
159 (4, 4),
160 (5, 11),
161 (6, 14),
162 ]);
163 assert_eq!(tail.len(), 7);
164 assert_eq!(tail.get(0), Some(5));
165 assert_eq!(tail.get(4), Some(4));
166 assert_eq!(tail.get(5), Some(11));
167 assert_eq!(tail.get(6), Some(14));
168
169 tail.push(2);
170 assert_eq!(tail.into_iter().collect_vec(), vec![
171 (0, 5),
172 (1, 3),
173 (2, 8),
174 (3, 9),
175 (4, 4),
176 (5, 11),
177 (6, 14),
178 (7, 2),
179 ]);
180 assert_eq!(tail.len(), 8);
181 assert_eq!(tail.get(0), Some(5));
182 assert_eq!(tail.get(4), Some(4));
183 assert_eq!(tail.get(5), Some(11));
184 assert_eq!(tail.get(6), Some(14));
185 assert_eq!(tail.get(7), Some(2));
186 assert_eq!(tail.get(8), None);
187 }
188}