1use crate::{BuddyCollection, BuddyLine, OligarchyCollection};
2use core::fmt;
3
4pub struct UsizeBuddy {
10 bits: usize,
12 base: usize,
14}
15
16impl UsizeBuddy {
17 const SIZE: usize = usize::BITS as usize;
18
19 #[inline]
20 fn take(&mut self, idx: usize) -> bool {
21 let bit = 1usize << idx;
22 let bits = self.bits;
23 self.bits &= !bit;
24 bits & bit == bit
25 }
26}
27
28impl BuddyLine for UsizeBuddy {
29 const EMPTY: Self = Self { bits: 0, base: 0 };
30
31 #[inline]
32 fn init(&mut self, _order: usize, base: usize) {
33 self.base = base;
34 }
35
36 #[inline]
37 fn take(&mut self, idx: usize) -> bool {
38 self.take(idx - self.base)
39 }
40}
41
42impl OligarchyCollection for UsizeBuddy {
43 #[inline]
44 fn take_any(&mut self, align_order: usize, count: usize) -> Option<usize> {
45 if count == 0 {
46 return None;
47 }
48 if count == 1 {
49 return BuddyCollection::take_any(self, align_order);
51 }
52
53 let mask = (1usize << count) - 1;
56 let align = 1usize << align_order;
57 let mut i = 0;
58 while i + count <= usize::BITS as usize {
59 let bits_mask = mask << i;
60 if self.bits & bits_mask == bits_mask {
61 self.bits &= !bits_mask;
62 return Some(self.base + i);
63 }
64 i += align;
65 }
66 None
67 }
68
69 #[inline]
70 fn put(&mut self, idx: usize) {
71 self.bits |= 1 << (idx - self.base);
72 }
73}
74
75impl BuddyCollection for UsizeBuddy {
76 #[inline]
77 fn take_any(&mut self, align_order: usize) -> Option<usize> {
78 if align_order == 0 {
83 if self.bits != 0 {
85 let i = self.bits.trailing_zeros() as usize;
86 self.bits &= !(1 << i);
87 return Some(self.base + i);
88 }
89 } else {
90 let align = 1usize << align_order;
92 let mut mask = 0usize;
94 for i in (0..usize::BITS as usize).step_by(align) {
95 mask |= 1 << i;
96 }
97 let aligned_bits = self.bits & mask;
98 if aligned_bits != 0 {
99 let i = aligned_bits.trailing_zeros() as usize;
100 self.bits &= !(1 << i);
101 return Some(self.base + i);
102 }
103 }
104 None
105 }
106
107 #[inline]
108 fn put(&mut self, idx: usize) -> Option<usize> {
109 let idx = idx - self.base;
110 debug_assert!(idx < Self::SIZE, "index out of bound");
111 let buddy = idx ^ 1;
112 if self.take(buddy) {
113 Some(idx << 1)
114 } else {
115 self.bits |= 1 << idx;
116 None
117 }
118 }
119}
120
121impl fmt::Debug for UsizeBuddy {
122 #[inline]
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 write!(f, "{:b}", self.bits)
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_buddy_line_init() {
134 let mut buddy = UsizeBuddy::EMPTY;
135 buddy.init(3, 10);
136 assert_eq!(buddy.base, 10);
137 }
138
139 #[test]
140 fn test_take_any_basic() {
141 let mut buddy = UsizeBuddy {
142 bits: 0b1010, base: 0,
144 };
145
146 assert_eq!(BuddyCollection::take_any(&mut buddy, 0), Some(1));
148 assert_eq!(BuddyCollection::take_any(&mut buddy, 0), Some(3));
150 assert_eq!(BuddyCollection::take_any(&mut buddy, 0), None);
152 }
153
154 #[test]
155 fn test_take_any_with_align() {
156 let mut buddy = UsizeBuddy {
157 bits: 0b1111, base: 0,
159 };
160
161 assert_eq!(BuddyCollection::take_any(&mut buddy, 1), Some(0));
164 assert_eq!(BuddyCollection::take_any(&mut buddy, 1), Some(2));
166 assert_eq!(BuddyCollection::take_any(&mut buddy, 1), None);
168 }
169
170 #[test]
171 fn test_put_basic() {
172 let mut buddy = UsizeBuddy {
173 bits: 0b0000,
174 base: 0,
175 };
176
177 assert_eq!(BuddyCollection::put(&mut buddy, 0), None);
179 assert_eq!(buddy.bits, 0b0001);
180
181 assert_eq!(BuddyCollection::put(&mut buddy, 2), None);
183 assert_eq!(buddy.bits, 0b0101);
184 }
185
186 #[test]
187 fn test_put_merge_buddy() {
188 let mut buddy = UsizeBuddy {
189 bits: 0b0001, base: 0,
191 };
192
193 assert_eq!(BuddyCollection::put(&mut buddy, 1), Some(2));
196 assert_eq!(buddy.bits, 0b0000);
197 }
198
199 #[test]
200 fn test_put_merge_buddy_base_offset() {
201 let mut buddy = UsizeBuddy {
203 bits: 0b0000, base: 10,
205 };
206
207 assert_eq!(BuddyCollection::put(&mut buddy, 10), None);
209 assert_eq!(buddy.bits, 0b0001);
210
211 assert_eq!(BuddyCollection::put(&mut buddy, 11), Some(2));
213 assert_eq!(buddy.bits, 0b0000);
214 }
215
216 #[test]
217 fn test_take_by_index() {
218 let mut buddy = UsizeBuddy {
219 bits: 0b1010,
220 base: 0,
221 };
222
223 assert!(buddy.take(3));
225 assert_eq!(buddy.bits, 0b0010);
226
227 assert!(!buddy.take(3));
229
230 assert!(buddy.take(1));
232 assert_eq!(buddy.bits, 0b0000);
233 }
234
235 #[test]
236 fn test_oligarchy_take_any_single() {
237 let mut buddy = UsizeBuddy {
238 bits: 0b1010,
239 base: 0,
240 };
241
242 assert_eq!(OligarchyCollection::take_any(&mut buddy, 0, 1), Some(1));
244 assert_eq!(OligarchyCollection::take_any(&mut buddy, 0, 1), Some(3));
245 assert_eq!(OligarchyCollection::take_any(&mut buddy, 0, 1), None);
246 }
247
248 #[test]
249 fn test_oligarchy_take_any_multiple() {
250 let mut buddy = UsizeBuddy {
251 bits: 0b0111, base: 0,
253 };
254
255 assert_eq!(OligarchyCollection::take_any(&mut buddy, 0, 2), Some(0));
257 assert_eq!(buddy.bits, 0b0100);
259
260 assert_eq!(OligarchyCollection::take_any(&mut buddy, 0, 2), None);
262 }
263
264 #[test]
265 fn test_oligarchy_take_any_count_zero() {
266 let mut buddy = UsizeBuddy {
267 bits: 0b1111,
268 base: 0,
269 };
270
271 assert_eq!(OligarchyCollection::take_any(&mut buddy, 0, 0), None);
273 assert_eq!(buddy.bits, 0b1111); }
275
276 #[test]
277 fn test_oligarchy_take_any_with_align() {
278 let mut buddy = UsizeBuddy {
279 bits: 0b111111, base: 0,
281 };
282
283 assert_eq!(OligarchyCollection::take_any(&mut buddy, 1, 2), Some(0));
287 assert_eq!(buddy.bits, 0b111100);
289
290 assert_eq!(OligarchyCollection::take_any(&mut buddy, 1, 2), Some(2));
294 assert_eq!(buddy.bits, 0b110000);
295 }
296
297 #[test]
298 fn test_empty() {
299 let buddy = UsizeBuddy::EMPTY;
300 assert_eq!(buddy.bits, 0);
301 assert_eq!(buddy.base, 0);
302 }
303}