1use core::{num::NonZeroUsize, ops::Range};
2
3use crate::DequeEnd;
4
5#[derive(Copy, Clone, Debug)]
7pub enum MetaLayout {
8 Empty,
10
11 Linear {
14 first: usize,
16
17 len: NonZeroUsize,
19 },
20
21 Wrapped {
24 wrap_len: NonZeroUsize,
28
29 gap_len: usize,
31 },
32}
33
34pub trait Meta: Clone + Sized {
36 fn capacity(&self) -> usize;
38
39 fn layout(&self) -> MetaLayout;
41
42 fn set_layout(&mut self, layout: MetaLayout);
44
45 fn len(&self) -> usize {
47 match self.layout() {
48 MetaLayout::Empty => 0,
49 MetaLayout::Linear { len, .. } => {
50 debug_assert!(len.get() <= self.capacity());
51 len.get()
52 }
53 MetaLayout::Wrapped { gap_len, .. } => {
54 let len = self.capacity() - gap_len;
55 debug_assert!(len <= self.capacity());
56 len
57 }
58 }
59 }
60
61 fn as_ranges(&self) -> (Range<usize>, Range<usize>) {
62 match self.layout() {
63 MetaLayout::Empty => (0..0, 0..0),
64 MetaLayout::Linear { first, len } => (first..first + len.get(), 0..0),
65 MetaLayout::Wrapped { wrap_len, gap_len } => {
66 let start = wrap_len.get() + gap_len;
67 (start..self.len(), 0..wrap_len.get())
68 }
69 }
70 }
71
72 fn clear(&mut self) -> MetaDrain<Self> {
75 let drain = MetaDrain {
76 meta: self.clone(),
77 remaining: self.len(),
78 end: DequeEnd::Front,
79 };
80
81 self.set_layout(MetaLayout::Empty);
82
83 drain
84 }
85
86 fn front(&self) -> Option<usize> {
90 match self.layout() {
91 MetaLayout::Empty => None,
92 MetaLayout::Linear { first, .. } => {
93 debug_assert!(first < self.capacity());
94 Some(first)
95 }
96 MetaLayout::Wrapped { wrap_len, gap_len } => {
97 let first = wrap_len.get() + gap_len;
98 debug_assert!(first < self.capacity());
99 Some(first)
100 }
101 }
102 }
103
104 fn back(&self) -> Option<usize> {
108 match self.layout() {
109 MetaLayout::Empty => None,
110 MetaLayout::Linear { first, len } => {
111 let last = first + len.get() - 1;
112 debug_assert!(last < self.capacity());
113 Some(last)
114 }
115 MetaLayout::Wrapped { wrap_len, .. } => {
116 let last = wrap_len.get() - 1;
117 debug_assert!(last < self.capacity());
118 Some(last)
119 }
120 }
121 }
122
123 fn reserve_front(&mut self) -> Option<usize> {
125 if self.capacity() == 0 {
126 return None;
127 }
128
129 match self.layout() {
130 MetaLayout::Empty => {
131 self.set_layout(MetaLayout::Linear {
132 first: self.capacity() - 1,
133 len: NonZeroUsize::new(1).unwrap(),
134 });
135
136 Some(self.capacity() - 1)
137 }
138
139 MetaLayout::Linear { len, .. } if len.get() == self.capacity() => None,
140
141 MetaLayout::Linear { first: 0, len } => {
142 self.set_layout(MetaLayout::Wrapped {
143 wrap_len: NonZeroUsize::new(1).unwrap(),
144 gap_len: self.capacity() - (len.get() + 1),
145 });
146
147 Some(self.capacity() - 1)
148 }
149
150 MetaLayout::Linear { first, len } => {
151 let new_first = first - 1;
152
153 self.set_layout(MetaLayout::Linear {
154 first: new_first,
155 len: NonZeroUsize::new(len.get() + 1).unwrap(),
156 });
157
158 Some(new_first)
159 }
160
161 MetaLayout::Wrapped { gap_len: 0, .. } => None,
163
164 MetaLayout::Wrapped { wrap_len, gap_len } => {
165 let new_gap_len = gap_len - 1;
166
167 self.set_layout(MetaLayout::Wrapped {
168 wrap_len,
169 gap_len: new_gap_len,
170 });
171
172 Some(wrap_len.get() + new_gap_len)
173 }
174 }
175 }
176
177 fn reserve_back(&mut self) -> Option<usize> {
179 if self.capacity() == 0 {
180 return None;
181 }
182
183 match self.layout() {
184 MetaLayout::Empty => {
185 self.set_layout(MetaLayout::Linear {
186 first: 0,
187 len: NonZeroUsize::new(1).unwrap(),
188 });
189
190 Some(0)
191 }
192
193 MetaLayout::Linear { len, .. } if len.get() == self.capacity() => None,
194
195 MetaLayout::Linear { first, len } if first + len.get() == self.capacity() => {
196 self.set_layout(MetaLayout::Wrapped {
197 wrap_len: NonZeroUsize::new(1).unwrap(),
198 gap_len: self.capacity() - (len.get() + 1),
199 });
200
201 Some(0)
202 }
203
204 MetaLayout::Linear { first, len } => {
205 let reserved = first + len.get();
206
207 self.set_layout(MetaLayout::Linear {
208 first,
209 len: NonZeroUsize::new(len.get() + 1).unwrap(),
210 });
211
212 Some(reserved)
213 }
214
215 MetaLayout::Wrapped { gap_len: 0, .. } => None,
216
217 MetaLayout::Wrapped { wrap_len, gap_len } => {
218 let reserved = wrap_len.get();
219
220 self.set_layout(MetaLayout::Wrapped {
221 wrap_len: NonZeroUsize::new(wrap_len.get() + 1).unwrap(),
222 gap_len: gap_len - 1,
223 });
224
225 Some(reserved)
226 }
227 }
228 }
229
230 fn free_front(&mut self) -> Option<usize> {
232 if self.capacity() == 0 {
233 return None;
234 }
235
236 match self.layout() {
237 MetaLayout::Empty => None,
238
239 MetaLayout::Linear { first, len } => {
240 let freed = first;
241
242 let new_layout = match NonZeroUsize::new(len.get() - 1) {
243 Some(new_len) => MetaLayout::Linear {
244 first: first + 1,
245 len: new_len,
246 },
247
248 None => MetaLayout::Empty,
249 };
250
251 self.set_layout(new_layout);
252
253 Some(freed)
254 }
255
256 MetaLayout::Wrapped { wrap_len, gap_len } => {
257 let freed = wrap_len.get() + gap_len;
258
259 let new_layout = if freed == self.capacity() - 1 {
260 MetaLayout::Linear {
261 first: 0,
262 len: wrap_len,
263 }
264 } else {
265 MetaLayout::Wrapped {
266 wrap_len,
267 gap_len: gap_len + 1,
268 }
269 };
270
271 self.set_layout(new_layout);
272
273 Some(freed)
274 }
275 }
276 }
277
278 fn drain_front(&mut self, n: usize) -> Option<MetaDrain<Self>> {
280 let drain = MetaDrain::front(self.clone(), n)?;
282
283 match self.layout() {
284 MetaLayout::Empty => (),
286
287 MetaLayout::Linear { first, len } => match NonZeroUsize::new(len.get() - n) {
288 Some(new_len) => {
289 self.set_layout(MetaLayout::Linear {
290 first: first + n,
291 len: new_len,
292 });
293 }
294
295 None => {
296 self.set_layout(MetaLayout::Empty);
297 }
298 },
299
300 MetaLayout::Wrapped { wrap_len, gap_len } => {
301 let front_len = self.capacity() - (wrap_len.get() + gap_len);
302
303 if n >= front_len {
304 let first = n - front_len;
305
306 match NonZeroUsize::new(wrap_len.get() - first) {
307 Some(new_len) => {
308 self.set_layout(MetaLayout::Linear {
309 first,
310 len: new_len,
311 });
312 }
313
314 None => self.set_layout(MetaLayout::Empty),
315 }
316 } else {
317 self.set_layout(MetaLayout::Wrapped {
318 wrap_len,
319 gap_len: gap_len + n,
320 });
321 }
322 }
323 }
324
325 Some(drain)
326 }
327
328 fn free_back(&mut self) -> Option<usize> {
330 if self.capacity() == 0 {
331 return None;
332 }
333
334 match self.layout() {
335 MetaLayout::Empty => None,
336
337 MetaLayout::Linear { first, len } => {
338 let freed = first + len.get() - 1;
339
340 let new_layout = match NonZeroUsize::new(len.get() - 1) {
341 Some(new_len) => MetaLayout::Linear {
342 first,
343 len: new_len,
344 },
345 None => MetaLayout::Empty,
346 };
347
348 self.set_layout(new_layout);
349
350 Some(freed)
351 }
352
353 MetaLayout::Wrapped { wrap_len, gap_len } => {
354 let (freed, new_layout) = match NonZeroUsize::new(wrap_len.get() - 1) {
355 Some(new_wrap_len) => (
356 new_wrap_len.get(),
357 MetaLayout::Wrapped {
358 wrap_len: new_wrap_len,
359 gap_len: gap_len + 1,
360 },
361 ),
362
363 None => (
364 0,
365 MetaLayout::Linear {
366 first: gap_len + 1,
367 len: NonZeroUsize::new(self.capacity() - (gap_len + 1)).unwrap(),
368 },
369 ),
370 };
371
372 self.set_layout(new_layout);
373
374 Some(freed)
375 }
376 }
377 }
378
379 fn drain_back(&mut self, n: usize) -> Option<MetaDrain<Self>> {
381 let drain = MetaDrain::back(self.clone(), n)?;
382
383 match self.layout() {
384 MetaLayout::Empty => (),
385
386 MetaLayout::Linear { first, len } => match NonZeroUsize::new(len.get() - n) {
387 Some(new_len) => {
388 self.set_layout(MetaLayout::Linear {
389 first,
390 len: new_len,
391 });
392 }
393
394 None => self.set_layout(MetaLayout::Empty),
395 },
396
397 MetaLayout::Wrapped { wrap_len, gap_len } => {
398 if n >= wrap_len.get() {
399 let total_len = self.capacity() - gap_len;
400
401 let new_layout = match NonZeroUsize::new(total_len - n) {
402 Some(new_len) => MetaLayout::Linear {
403 first: wrap_len.get() + gap_len,
404 len: new_len,
405 },
406 None => MetaLayout::Empty,
407 };
408
409 self.set_layout(new_layout);
410 } else {
411 self.set_layout(MetaLayout::Wrapped {
412 wrap_len: NonZeroUsize::new(wrap_len.get() - n).unwrap(),
413 gap_len: gap_len + n,
414 });
415 }
416 }
417 }
418
419 Some(drain)
420 }
421}
422
423pub struct MetaDrain<M>
424where
425 M: Meta,
426{
427 meta: M,
428 remaining: usize,
429 end: DequeEnd,
430}
431
432impl<M> MetaDrain<M>
433where
434 M: Meta,
435{
436 pub fn front(meta: M, n: usize) -> Option<MetaDrain<M>> {
440 if n > meta.len() {
441 None
442 } else {
443 Some(MetaDrain {
444 meta,
445 remaining: n,
446 end: DequeEnd::Front,
447 })
448 }
449 }
450
451 pub fn back(meta: M, n: usize) -> Option<MetaDrain<M>> {
455 if n > meta.len() {
456 None
457 } else {
458 Some(MetaDrain {
459 meta,
460 remaining: n,
461 end: DequeEnd::Back,
462 })
463 }
464 }
465}
466
467impl<M> Iterator for MetaDrain<M>
468where
469 M: Meta,
470{
471 type Item = usize;
472
473 fn next(&mut self) -> Option<Self::Item> {
474 if self.remaining > 0 {
475 self.remaining -= 1;
476
477 let index = match self.end {
478 DequeEnd::Front => self.meta.free_front().unwrap(),
479 DequeEnd::Back => self.meta.free_back().unwrap(),
480 };
481
482 Some(index)
483 } else {
484 None
485 }
486 }
487
488 fn size_hint(&self) -> (usize, Option<usize>) {
489 (self.remaining, Some(self.remaining))
490 }
491}