]> git.proxmox.com Git - cargo.git/blob - vendor/im-rc/src/nodes/unsafe_chunks/sized_chunk.rs
New upstream version 0.33.0
[cargo.git] / vendor / im-rc / src / nodes / unsafe_chunks / sized_chunk.rs
1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5 //! A fixed capacity smart array.
6 //!
7 //! See [`Chunk`](struct.Chunk.html)
8
9 use std::borrow::{Borrow, BorrowMut};
10 use std::cmp::Ordering;
11 use std::fmt::{Debug, Error, Formatter};
12 use std::hash::{Hash, Hasher};
13 use std::io;
14 use std::iter::{FromIterator, FusedIterator};
15 use std::mem::{self, replace, ManuallyDrop};
16 use std::ops::{Deref, DerefMut, Index, IndexMut};
17 use std::ptr;
18 use std::slice::{
19 from_raw_parts, from_raw_parts_mut, Iter as SliceIter, IterMut as SliceIterMut, SliceIndex,
20 };
21
22 use typenum::U64;
23
24 use nodes::types::ChunkLength;
25
26 /// A fixed capacity smart array.
27 ///
28 /// An inline array of items with a variable length but a fixed, preallocated
29 /// capacity given by the `N` type, which must be an [`Unsigned`][Unsigned] type
30 /// level numeral.
31 ///
32 /// It's 'smart' because it's able to reorganise its contents based on expected
33 /// behaviour. If you construct one using `push_back`, it will be laid out like
34 /// a `Vec` with space at the end. If you `push_front` it will start filling in
35 /// values from the back instead of the front, so that you still get linear time
36 /// push as long as you don't reverse direction. If you do, and there's no room
37 /// at the end you're pushing to, it'll shift its contents over to the other
38 /// side, creating more space to push into. This technique is tuned for
39 /// `Chunk`'s expected use case: usually, chunks always see either `push_front`
40 /// or `push_back`, but not both unless they move around inside the tree, in
41 /// which case they're able to reorganise themselves with reasonable efficiency
42 /// to suit their new usage patterns.
43 ///
44 /// It maintains a `left` index and a `right` index instead of a simple length
45 /// counter in order to accomplish this, much like a ring buffer would, except
46 /// that the `Chunk` keeps all its items sequentially in memory so that you can
47 /// always get a `&[A]` slice for them, at the price of the occasional
48 /// reordering operation.
49 ///
50 /// This technique also lets us choose to shift the shortest side to account for
51 /// the inserted or removed element when performing insert and remove
52 /// operations, unlike `Vec` where you always need to shift the right hand side.
53 ///
54 /// Unlike a `Vec`, the `Chunk` has a fixed capacity and cannot grow beyond it.
55 /// Being intended for low level use, it expects you to know or test whether
56 /// you're pushing to a full array, and has an API more geared towards panics
57 /// than returning `Option`s, on the assumption that you know what you're doing.
58 ///
59 /// # Examples
60 ///
61 /// ```rust
62 /// # #[macro_use] extern crate im_rc as im;
63 /// # extern crate typenum;
64 /// # use im::chunk::Chunk;
65 /// # use typenum::U64;
66 /// # fn main() {
67 /// // Construct a chunk with a 64 item capacity
68 /// let mut chunk = Chunk::<i32, U64>::new();
69 /// // Fill it with descending numbers
70 /// chunk.extend((0..64).rev());
71 /// // It derefs to a slice so we can use standard slice methods
72 /// chunk.sort();
73 /// // It's got all the amenities like `FromIterator` and `Eq`
74 /// let expected: Chunk<i32, U64> = (0..64).collect();
75 /// assert_eq!(expected, chunk);
76 /// # }
77 /// ```
78 ///
79 /// [Unsigned]: https://docs.rs/typenum/1.10.0/typenum/marker_traits/trait.Unsigned.html
80 pub struct Chunk<A, N = U64>
81 where
82 N: ChunkLength<A>,
83 {
84 left: usize,
85 right: usize,
86 data: ManuallyDrop<N::SizedType>,
87 }
88
89 impl<A, N> Drop for Chunk<A, N>
90 where
91 N: ChunkLength<A>,
92 {
93 fn drop(&mut self) {
94 if mem::needs_drop::<A>() {
95 for i in self.left..self.right {
96 unsafe { Chunk::force_drop(i, self) }
97 }
98 }
99 }
100 }
101
102 impl<A, N> Clone for Chunk<A, N>
103 where
104 A: Clone,
105 N: ChunkLength<A>,
106 {
107 fn clone(&self) -> Self {
108 let mut out = Self::new();
109 out.left = self.left;
110 out.right = self.right;
111 for index in self.left..self.right {
112 unsafe { Chunk::force_write(index, self.values()[index].clone(), &mut out) }
113 }
114 out
115 }
116 }
117
118 impl<A, N> Chunk<A, N>
119 where
120 N: ChunkLength<A>,
121 {
122 /// Construct a new empty chunk.
123 pub fn new() -> Self {
124 let mut chunk: Self;
125 unsafe {
126 chunk = mem::uninitialized();
127 ptr::write(&mut chunk.left, 0);
128 ptr::write(&mut chunk.right, 0);
129 }
130 chunk
131 }
132
133 /// Construct a new chunk with one item.
134 pub fn unit(value: A) -> Self {
135 let mut chunk: Self;
136 unsafe {
137 chunk = mem::uninitialized();
138 ptr::write(&mut chunk.left, 0);
139 ptr::write(&mut chunk.right, 1);
140 Chunk::force_write(0, value, &mut chunk);
141 }
142 chunk
143 }
144
145 /// Construct a new chunk with two items.
146 pub fn pair(left: A, right: A) -> Self {
147 let mut chunk: Self;
148 unsafe {
149 chunk = mem::uninitialized();
150 ptr::write(&mut chunk.left, 0);
151 ptr::write(&mut chunk.right, 2);
152 Chunk::force_write(0, left, &mut chunk);
153 Chunk::force_write(1, right, &mut chunk);
154 }
155 chunk
156 }
157
158 /// Construct a new chunk and move every item from `other` into the new
159 /// chunk.
160 ///
161 /// Time: O(n)
162 pub fn drain_from(other: &mut Self) -> Self {
163 let other_len = other.len();
164 Self::from_front(other, other_len)
165 }
166
167 /// Construct a new chunk and populate it by taking `count` items from the
168 /// iterator `iter`.
169 ///
170 /// Panics if the iterator contains less than `count` items.
171 ///
172 /// Time: O(n)
173 pub fn collect_from<I>(iter: &mut I, mut count: usize) -> Self
174 where
175 I: Iterator<Item = A>,
176 {
177 let mut chunk = Self::new();
178 while count > 0 {
179 count -= 1;
180 chunk.push_back(
181 iter.next()
182 .expect("Chunk::collect_from: underfull iterator"),
183 );
184 }
185 chunk
186 }
187
188 /// Construct a new chunk and populate it by taking `count` items from the
189 /// front of `other`.
190 ///
191 /// Time: O(n) for the number of items moved
192 pub fn from_front(other: &mut Self, count: usize) -> Self {
193 let other_len = other.len();
194 debug_assert!(count <= other_len);
195 let mut chunk = Self::new();
196 unsafe { Chunk::force_copy_to(other.left, 0, count, other, &mut chunk) };
197 chunk.right = count;
198 other.left += count;
199 chunk
200 }
201
202 /// Construct a new chunk and populate it by taking `count` items from the
203 /// back of `other`.
204 ///
205 /// Time: O(n) for the number of items moved
206 pub fn from_back(other: &mut Self, count: usize) -> Self {
207 let other_len = other.len();
208 debug_assert!(count <= other_len);
209 let mut chunk = Self::new();
210 unsafe { Chunk::force_copy_to(other.right - count, 0, count, other, &mut chunk) };
211 chunk.right = count;
212 other.right -= count;
213 chunk
214 }
215
216 /// Get the length of the chunk.
217 #[inline]
218 pub fn len(&self) -> usize {
219 self.right - self.left
220 }
221
222 /// Test if the chunk is empty.
223 #[inline]
224 pub fn is_empty(&self) -> bool {
225 self.left == self.right
226 }
227
228 /// Test if the chunk is at capacity.
229 #[inline]
230 pub fn is_full(&self) -> bool {
231 self.left == 0 && self.right == N::USIZE
232 }
233
234 #[inline]
235 fn values(&self) -> &[A] {
236 unsafe {
237 from_raw_parts(
238 &self.data as *const ManuallyDrop<N::SizedType> as *const A,
239 N::USIZE,
240 )
241 }
242 }
243
244 #[inline]
245 fn values_mut(&mut self) -> &mut [A] {
246 unsafe {
247 from_raw_parts_mut(
248 &mut self.data as *mut ManuallyDrop<N::SizedType> as *mut A,
249 N::USIZE,
250 )
251 }
252 }
253
254 /// Copy the value at an index, discarding ownership of the copied value
255 #[inline]
256 unsafe fn force_read(index: usize, chunk: &mut Self) -> A {
257 ptr::read(&chunk.values()[index])
258 }
259
260 /// Write a value at an index without trying to drop what's already there
261 #[inline]
262 unsafe fn force_write(index: usize, value: A, chunk: &mut Self) {
263 ptr::write(&mut chunk.values_mut()[index], value)
264 }
265
266 /// Drop the value at an index
267 #[inline]
268 unsafe fn force_drop(index: usize, chunk: &mut Self) {
269 ptr::drop_in_place(&mut chunk.values_mut()[index])
270 }
271
272 /// Copy a range within a chunk
273 #[inline]
274 unsafe fn force_copy(from: usize, to: usize, count: usize, chunk: &mut Self) {
275 if count > 0 {
276 ptr::copy(&chunk.values()[from], &mut chunk.values_mut()[to], count)
277 }
278 }
279
280 /// Copy a range between chunks
281 #[inline]
282 unsafe fn force_copy_to(
283 from: usize,
284 to: usize,
285 count: usize,
286 chunk: &mut Self,
287 other: &mut Self,
288 ) {
289 if count > 0 {
290 ptr::copy_nonoverlapping(&chunk.values()[from], &mut other.values_mut()[to], count)
291 }
292 }
293
294 /// Push an item to the front of the chunk.
295 ///
296 /// Panics if the capacity of the chunk is exceeded.
297 ///
298 /// Time: O(1) if there's room at the front, O(n) otherwise
299 pub fn push_front(&mut self, value: A) {
300 if self.is_full() {
301 panic!("Chunk::push_front: can't push to full chunk");
302 }
303 if self.is_empty() {
304 self.left = N::USIZE;
305 self.right = N::USIZE;
306 } else if self.left == 0 {
307 self.left = N::USIZE - self.right;
308 unsafe { Chunk::force_copy(0, self.left, self.right, self) };
309 self.right = N::USIZE;
310 }
311 self.left -= 1;
312 unsafe { Chunk::force_write(self.left, value, self) }
313 }
314
315 /// Push an item to the back of the chunk.
316 ///
317 /// Panics if the capacity of the chunk is exceeded.
318 ///
319 /// Time: O(1) if there's room at the back, O(n) otherwise
320 pub fn push_back(&mut self, value: A) {
321 if self.is_full() {
322 panic!("Chunk::push_back: can't push to full chunk");
323 }
324 if self.is_empty() {
325 self.left = 0;
326 self.right = 0;
327 } else if self.right == N::USIZE {
328 unsafe { Chunk::force_copy(self.left, 0, self.len(), self) };
329 self.right = N::USIZE - self.left;
330 self.left = 0;
331 }
332 unsafe { Chunk::force_write(self.right, value, self) }
333 self.right += 1;
334 }
335
336 /// Pop an item off the front of the chunk.
337 ///
338 /// Panics if the chunk is empty.
339 ///
340 /// Time: O(1)
341 pub fn pop_front(&mut self) -> A {
342 if self.is_empty() {
343 panic!("Chunk::pop_front: can't pop from empty chunk");
344 } else {
345 let value = unsafe { Chunk::force_read(self.left, self) };
346 self.left += 1;
347 value
348 }
349 }
350
351 /// Pop an item off the back of the chunk.
352 ///
353 /// Panics if the chunk is empty.
354 ///
355 /// Time: O(1)
356 pub fn pop_back(&mut self) -> A {
357 if self.is_empty() {
358 panic!("Chunk::pop_back: can't pop from empty chunk");
359 } else {
360 self.right -= 1;
361 unsafe { Chunk::force_read(self.right, self) }
362 }
363 }
364
365 /// Discard all items up to but not including `index`.
366 ///
367 /// Panics if `index` is out of bounds.
368 ///
369 /// Time: O(n) for the number of items dropped
370 pub fn drop_left(&mut self, index: usize) {
371 if index > 0 {
372 if index > self.len() {
373 panic!("Chunk::drop_left: index out of bounds");
374 }
375 let start = self.left;
376 for i in start..(start + index) {
377 unsafe { Chunk::force_drop(i, self) }
378 }
379 self.left += index;
380 }
381 }
382
383 /// Discard all items from `index` onward.
384 ///
385 /// Panics if `index` is out of bounds.
386 ///
387 /// Time: O(n) for the number of items dropped
388 pub fn drop_right(&mut self, index: usize) {
389 if index > self.len() {
390 panic!("Chunk::drop_right: index out of bounds");
391 }
392 if index == self.len() {
393 return;
394 }
395 let start = self.left + index;
396 for i in start..self.right {
397 unsafe { Chunk::force_drop(i, self) }
398 }
399 self.right = start;
400 }
401
402 /// Split a chunk into two, the original chunk containing
403 /// everything up to `index` and the returned chunk containing
404 /// everything from `index` onwards.
405 ///
406 /// Panics if `index` is out of bounds.
407 ///
408 /// Time: O(n) for the number of items in the new chunk
409 pub fn split_off(&mut self, index: usize) -> Self {
410 if index > self.len() {
411 panic!("Chunk::split: index out of bounds");
412 }
413 if index == self.len() {
414 return Self::new();
415 }
416 let mut right_chunk = Self::new();
417 let start = self.left + index;
418 let len = self.right - start;
419 unsafe { Chunk::force_copy_to(start, 0, len, self, &mut right_chunk) };
420 right_chunk.right = len;
421 self.right = start;
422 right_chunk
423 }
424
425 /// Remove all items from `other` and append them to the back of `self`.
426 ///
427 /// Panics if the capacity of the chunk is exceeded.
428 ///
429 /// Time: O(n) for the number of items moved
430 pub fn append(&mut self, other: &mut Self) {
431 let self_len = self.len();
432 let other_len = other.len();
433 if self_len + other_len > N::USIZE {
434 panic!("Chunk::append: chunk size overflow");
435 }
436 if self.right + other_len > N::USIZE {
437 unsafe { Chunk::force_copy(self.left, 0, self_len, self) };
438 self.right -= self.left;
439 self.left = 0;
440 }
441 unsafe { Chunk::force_copy_to(other.left, self.right, other_len, other, self) };
442 self.right += other_len;
443 other.left = 0;
444 other.right = 0;
445 }
446
447 /// Remove `count` items from the front of `other` and append them to the
448 /// back of `self`.
449 ///
450 /// Panics if `self` doesn't have `count` items left, or if `other` has
451 /// fewer than `count` items.
452 ///
453 /// Time: O(n) for the number of items moved
454 pub fn drain_from_front(&mut self, other: &mut Self, count: usize) {
455 let self_len = self.len();
456 let other_len = other.len();
457 debug_assert!(self_len + count <= N::USIZE);
458 debug_assert!(other_len >= count);
459 if self.right + count > N::USIZE {
460 unsafe { Chunk::force_copy(self.left, 0, self_len, self) };
461 self.right -= self.left;
462 self.left = 0;
463 }
464 unsafe { Chunk::force_copy_to(other.left, self.right, count, other, self) };
465 self.right += count;
466 other.left += count;
467 }
468
469 /// Remove `count` items from the back of `other` and append them to the
470 /// front of `self`.
471 ///
472 /// Panics if `self` doesn't have `count` items left, or if `other` has
473 /// fewer than `count` items.
474 ///
475 /// Time: O(n) for the number of items moved
476 pub fn drain_from_back(&mut self, other: &mut Self, count: usize) {
477 let self_len = self.len();
478 let other_len = other.len();
479 debug_assert!(self_len + count <= N::USIZE);
480 debug_assert!(other_len >= count);
481 if self.left < count {
482 self.left = N::USIZE - self.right;
483 unsafe { Chunk::force_copy(0, self.left, self.right, self) };
484 self.right = N::USIZE;
485 }
486 unsafe { Chunk::force_copy_to(other.right - count, self.left - count, count, other, self) };
487 self.left -= count;
488 other.right -= count;
489 }
490
491 /// Update the value at index `index`, returning the old value.
492 ///
493 /// Panics if `index` is out of bounds.
494 ///
495 /// Time: O(1)
496 pub fn set(&mut self, index: usize, value: A) -> A {
497 replace(&mut self[index], value)
498 }
499
500 /// Insert a new value at index `index`, shifting all the following values
501 /// to the right.
502 ///
503 /// Panics if the index is out of bounds.
504 ///
505 /// Time: O(n) for the number of items shifted
506 pub fn insert(&mut self, index: usize, value: A) {
507 if self.is_full() {
508 panic!("Chunk::insert: chunk is full");
509 }
510 if index > self.len() {
511 panic!("Chunk::insert: index out of bounds");
512 }
513 let real_index = index + self.left;
514 let left_size = index;
515 let right_size = self.right - real_index;
516 if self.right == N::USIZE || (self.left > 0 && left_size < right_size) {
517 unsafe {
518 Chunk::force_copy(self.left, self.left - 1, left_size, self);
519 Chunk::force_write(real_index - 1, value, self);
520 }
521 self.left -= 1;
522 } else {
523 unsafe {
524 Chunk::force_copy(real_index, real_index + 1, right_size, self);
525 Chunk::force_write(real_index, value, self);
526 }
527 self.right += 1;
528 }
529 }
530
531 /// Remove the value at index `index`, shifting all the following values to
532 /// the left.
533 ///
534 /// Returns the removed value.
535 ///
536 /// Panics if the index is out of bounds.
537 ///
538 /// Time: O(n) for the number of items shifted
539 pub fn remove(&mut self, index: usize) -> A {
540 if index >= self.len() {
541 panic!("Chunk::remove: index out of bounds");
542 }
543 let real_index = index + self.left;
544 let value = unsafe { Chunk::force_read(real_index, self) };
545 let left_size = index;
546 let right_size = self.right - real_index - 1;
547 if left_size < right_size {
548 unsafe { Chunk::force_copy(self.left, self.left + 1, left_size, self) };
549 self.left += 1;
550 } else {
551 unsafe { Chunk::force_copy(real_index + 1, real_index, right_size, self) };
552 self.right -= 1;
553 }
554 value
555 }
556
557 /// Construct an iterator that drains values from the front of the chunk.
558 pub fn drain(&mut self) -> Drain<'_, A, N> {
559 Drain { chunk: self }
560 }
561
562 /// Discard the contents of the chunk.
563 ///
564 /// Time: O(n)
565 pub fn clear(&mut self) {
566 self.drop_right(0);
567 self.left = 0;
568 self.right = 0;
569 }
570
571 /// Get a reference to the contents of the chunk as a slice.
572 pub fn as_slice(&self) -> &[A] {
573 unsafe {
574 from_raw_parts(
575 (&self.data as *const ManuallyDrop<N::SizedType> as *const A).add(self.left),
576 self.len(),
577 )
578 }
579 }
580
581 /// Get a reference to the contents of the chunk as a mutable slice.
582 pub fn as_mut_slice(&mut self) -> &mut [A] {
583 unsafe {
584 from_raw_parts_mut(
585 (&mut self.data as *mut ManuallyDrop<N::SizedType> as *mut A).add(self.left),
586 self.len(),
587 )
588 }
589 }
590 }
591
592 impl<A, N> Default for Chunk<A, N>
593 where
594 N: ChunkLength<A>,
595 {
596 fn default() -> Self {
597 Self::new()
598 }
599 }
600
601 impl<A, N, I> Index<I> for Chunk<A, N>
602 where
603 I: SliceIndex<[A]>,
604 N: ChunkLength<A>,
605 {
606 type Output = I::Output;
607 fn index(&self, index: I) -> &Self::Output {
608 self.as_slice().index(index)
609 }
610 }
611
612 impl<A, N, I> IndexMut<I> for Chunk<A, N>
613 where
614 I: SliceIndex<[A]>,
615 N: ChunkLength<A>,
616 {
617 fn index_mut(&mut self, index: I) -> &mut Self::Output {
618 self.as_mut_slice().index_mut(index)
619 }
620 }
621
622 impl<A, N> Debug for Chunk<A, N>
623 where
624 A: Debug,
625 N: ChunkLength<A>,
626 {
627 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
628 f.write_str("Chunk")?;
629 f.debug_list().entries(self.iter()).finish()
630 }
631 }
632
633 impl<A, N> Hash for Chunk<A, N>
634 where
635 A: Hash,
636 N: ChunkLength<A>,
637 {
638 fn hash<H>(&self, hasher: &mut H)
639 where
640 H: Hasher,
641 {
642 for item in self {
643 item.hash(hasher)
644 }
645 }
646 }
647
648 impl<A, N> PartialEq for Chunk<A, N>
649 where
650 A: PartialEq,
651 N: ChunkLength<A>,
652 {
653 fn eq(&self, other: &Self) -> bool {
654 self.len() == other.len() && self.iter().eq(other.iter())
655 }
656 }
657
658 impl<A, N> Eq for Chunk<A, N>
659 where
660 A: Eq,
661 N: ChunkLength<A>,
662 {
663 }
664
665 impl<A, N> PartialOrd for Chunk<A, N>
666 where
667 A: PartialOrd,
668 N: ChunkLength<A>,
669 {
670 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
671 self.iter().partial_cmp(other.iter())
672 }
673 }
674
675 impl<A, N> Ord for Chunk<A, N>
676 where
677 A: Ord,
678 N: ChunkLength<A>,
679 {
680 fn cmp(&self, other: &Self) -> Ordering {
681 self.iter().cmp(other.iter())
682 }
683 }
684
685 impl<N> io::Write for Chunk<u8, N>
686 where
687 N: ChunkLength<u8>,
688 {
689 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
690 let old_len = self.len();
691 self.extend(buf.iter().cloned().take(N::USIZE - old_len));
692 Ok(self.len() - old_len)
693 }
694
695 fn flush(&mut self) -> io::Result<()> {
696 Ok(())
697 }
698 }
699
700 impl<A, N> Borrow<[A]> for Chunk<A, N>
701 where
702 N: ChunkLength<A>,
703 {
704 fn borrow(&self) -> &[A] {
705 self.as_slice()
706 }
707 }
708
709 impl<A, N> BorrowMut<[A]> for Chunk<A, N>
710 where
711 N: ChunkLength<A>,
712 {
713 fn borrow_mut(&mut self) -> &mut [A] {
714 self.as_mut_slice()
715 }
716 }
717
718 impl<A, N> AsRef<[A]> for Chunk<A, N>
719 where
720 N: ChunkLength<A>,
721 {
722 fn as_ref(&self) -> &[A] {
723 self.as_slice()
724 }
725 }
726
727 impl<A, N> AsMut<[A]> for Chunk<A, N>
728 where
729 N: ChunkLength<A>,
730 {
731 fn as_mut(&mut self) -> &mut [A] {
732 self.as_mut_slice()
733 }
734 }
735
736 impl<A, N> Deref for Chunk<A, N>
737 where
738 N: ChunkLength<A>,
739 {
740 type Target = [A];
741
742 fn deref(&self) -> &Self::Target {
743 self.as_slice()
744 }
745 }
746
747 impl<A, N> DerefMut for Chunk<A, N>
748 where
749 N: ChunkLength<A>,
750 {
751 fn deref_mut(&mut self) -> &mut Self::Target {
752 self.as_mut_slice()
753 }
754 }
755
756 impl<A, N> FromIterator<A> for Chunk<A, N>
757 where
758 N: ChunkLength<A>,
759 {
760 fn from_iter<I>(it: I) -> Self
761 where
762 I: IntoIterator<Item = A>,
763 {
764 let mut chunk = Self::new();
765 for item in it {
766 chunk.push_back(item);
767 }
768 chunk
769 }
770 }
771
772 impl<'a, A, N> IntoIterator for &'a Chunk<A, N>
773 where
774 N: ChunkLength<A>,
775 {
776 type Item = &'a A;
777 type IntoIter = SliceIter<'a, A>;
778 fn into_iter(self) -> Self::IntoIter {
779 self.iter()
780 }
781 }
782
783 impl<'a, A, N> IntoIterator for &'a mut Chunk<A, N>
784 where
785 N: ChunkLength<A>,
786 {
787 type Item = &'a mut A;
788 type IntoIter = SliceIterMut<'a, A>;
789 fn into_iter(self) -> Self::IntoIter {
790 self.iter_mut()
791 }
792 }
793
794 impl<A, N> Extend<A> for Chunk<A, N>
795 where
796 N: ChunkLength<A>,
797 {
798 /// Append the contents of the iterator to the back of the chunk.
799 ///
800 /// Panics if the chunk exceeds its capacity.
801 ///
802 /// Time: O(n) for the length of the iterator
803 fn extend<I>(&mut self, it: I)
804 where
805 I: IntoIterator<Item = A>,
806 {
807 for item in it {
808 self.push_back(item);
809 }
810 }
811 }
812
813 impl<'a, A, N> Extend<&'a A> for Chunk<A, N>
814 where
815 A: 'a + Copy,
816 N: ChunkLength<A>,
817 {
818 /// Append the contents of the iterator to the back of the chunk.
819 ///
820 /// Panics if the chunk exceeds its capacity.
821 ///
822 /// Time: O(n) for the length of the iterator
823 fn extend<I>(&mut self, it: I)
824 where
825 I: IntoIterator<Item = &'a A>,
826 {
827 for item in it {
828 self.push_back(*item);
829 }
830 }
831 }
832
833 pub struct Iter<A, N>
834 where
835 N: ChunkLength<A>,
836 {
837 chunk: Chunk<A, N>,
838 }
839
840 impl<A, N> Iterator for Iter<A, N>
841 where
842 N: ChunkLength<A>,
843 {
844 type Item = A;
845 fn next(&mut self) -> Option<Self::Item> {
846 if self.chunk.is_empty() {
847 None
848 } else {
849 Some(self.chunk.pop_front())
850 }
851 }
852
853 fn size_hint(&self) -> (usize, Option<usize>) {
854 (self.chunk.len(), Some(self.chunk.len()))
855 }
856 }
857
858 impl<A, N> DoubleEndedIterator for Iter<A, N>
859 where
860 N: ChunkLength<A>,
861 {
862 fn next_back(&mut self) -> Option<Self::Item> {
863 if self.chunk.is_empty() {
864 None
865 } else {
866 Some(self.chunk.pop_back())
867 }
868 }
869 }
870
871 impl<A, N> ExactSizeIterator for Iter<A, N> where N: ChunkLength<A> {}
872
873 impl<A, N> FusedIterator for Iter<A, N> where N: ChunkLength<A> {}
874
875 impl<A, N> IntoIterator for Chunk<A, N>
876 where
877 N: ChunkLength<A>,
878 {
879 type Item = A;
880 type IntoIter = Iter<A, N>;
881
882 fn into_iter(self) -> Self::IntoIter {
883 Iter { chunk: self }
884 }
885 }
886
887 pub struct Drain<'a, A, N>
888 where
889 A: 'a,
890 N: ChunkLength<A> + 'a,
891 {
892 chunk: &'a mut Chunk<A, N>,
893 }
894
895 impl<'a, A, N> Iterator for Drain<'a, A, N>
896 where
897 A: 'a,
898 N: ChunkLength<A> + 'a,
899 {
900 type Item = A;
901
902 fn next(&mut self) -> Option<Self::Item> {
903 if self.chunk.is_empty() {
904 None
905 } else {
906 Some(self.chunk.pop_front())
907 }
908 }
909
910 fn size_hint(&self) -> (usize, Option<usize>) {
911 (self.chunk.len(), Some(self.chunk.len()))
912 }
913 }
914
915 impl<'a, A, N> ExactSizeIterator for Drain<'a, A, N>
916 where
917 A: 'a,
918 N: ChunkLength<A> + 'a,
919 {
920 }
921
922 impl<'a, A, N> FusedIterator for Drain<'a, A, N>
923 where
924 A: 'a,
925 N: ChunkLength<A> + 'a,
926 {
927 }
928
929 #[cfg(test)]
930 mod test {
931 use super::*;
932
933 #[test]
934 fn is_full() {
935 let mut chunk = Chunk::<_, U64>::new();
936 for i in 0..64 {
937 assert_eq!(false, chunk.is_full());
938 chunk.push_back(i);
939 }
940 assert_eq!(true, chunk.is_full());
941 }
942
943 #[test]
944 fn push_back_front() {
945 let mut chunk = Chunk::<_, U64>::new();
946 for i in 12..20 {
947 chunk.push_back(i);
948 }
949 assert_eq!(8, chunk.len());
950 for i in (0..12).rev() {
951 chunk.push_front(i);
952 }
953 assert_eq!(20, chunk.len());
954 for i in 20..32 {
955 chunk.push_back(i);
956 }
957 assert_eq!(32, chunk.len());
958 let right: Vec<i32> = chunk.into_iter().collect();
959 let left: Vec<i32> = (0..32).collect();
960 assert_eq!(left, right);
961 }
962
963 #[test]
964 fn push_and_pop() {
965 let mut chunk = Chunk::<_, U64>::new();
966 for i in 0..64 {
967 chunk.push_back(i);
968 }
969 for i in 0..64 {
970 assert_eq!(i, chunk.pop_front());
971 }
972 for i in 0..64 {
973 chunk.push_front(i);
974 }
975 for i in 0..64 {
976 assert_eq!(i, chunk.pop_back());
977 }
978 }
979
980 #[test]
981 fn drop_left() {
982 let mut chunk = Chunk::<_, U64>::new();
983 for i in 0..6 {
984 chunk.push_back(i);
985 }
986 chunk.drop_left(3);
987 let vec: Vec<i32> = chunk.into_iter().collect();
988 assert_eq!(vec![3, 4, 5], vec);
989 }
990
991 #[test]
992 fn drop_right() {
993 let mut chunk = Chunk::<_, U64>::new();
994 for i in 0..6 {
995 chunk.push_back(i);
996 }
997 chunk.drop_right(3);
998 let vec: Vec<i32> = chunk.into_iter().collect();
999 assert_eq!(vec![0, 1, 2], vec);
1000 }
1001
1002 #[test]
1003 fn split_off() {
1004 let mut left = Chunk::<_, U64>::new();
1005 for i in 0..6 {
1006 left.push_back(i);
1007 }
1008 let right = left.split_off(3);
1009 let left_vec: Vec<i32> = left.into_iter().collect();
1010 let right_vec: Vec<i32> = right.into_iter().collect();
1011 assert_eq!(vec![0, 1, 2], left_vec);
1012 assert_eq!(vec![3, 4, 5], right_vec);
1013 }
1014
1015 #[test]
1016 fn append() {
1017 let mut left = Chunk::<_, U64>::new();
1018 for i in 0..32 {
1019 left.push_back(i);
1020 }
1021 let mut right = Chunk::<_, U64>::new();
1022 for i in (32..64).rev() {
1023 right.push_front(i);
1024 }
1025 left.append(&mut right);
1026 let out_vec: Vec<i32> = left.into_iter().collect();
1027 let should_vec: Vec<i32> = (0..64).collect();
1028 assert_eq!(should_vec, out_vec);
1029 }
1030
1031 #[test]
1032 fn ref_iter() {
1033 let mut chunk = Chunk::<_, U64>::new();
1034 for i in 0..64 {
1035 chunk.push_back(i);
1036 }
1037 let out_vec: Vec<&i32> = chunk.iter().collect();
1038 let should_vec_p: Vec<i32> = (0..64).collect();
1039 let should_vec: Vec<&i32> = should_vec_p.iter().collect();
1040 assert_eq!(should_vec, out_vec);
1041 }
1042
1043 #[test]
1044 fn mut_ref_iter() {
1045 let mut chunk = Chunk::<_, U64>::new();
1046 for i in 0..64 {
1047 chunk.push_back(i);
1048 }
1049 let out_vec: Vec<&mut i32> = chunk.iter_mut().collect();
1050 let mut should_vec_p: Vec<i32> = (0..64).collect();
1051 let should_vec: Vec<&mut i32> = should_vec_p.iter_mut().collect();
1052 assert_eq!(should_vec, out_vec);
1053 }
1054
1055 #[test]
1056 fn consuming_iter() {
1057 let mut chunk = Chunk::<_, U64>::new();
1058 for i in 0..64 {
1059 chunk.push_back(i);
1060 }
1061 let out_vec: Vec<i32> = chunk.into_iter().collect();
1062 let should_vec: Vec<i32> = (0..64).collect();
1063 assert_eq!(should_vec, out_vec);
1064 }
1065
1066 #[test]
1067 fn insert_middle() {
1068 let mut chunk = Chunk::<_, U64>::new();
1069 for i in 0..32 {
1070 chunk.push_back(i);
1071 }
1072 for i in 33..64 {
1073 chunk.push_back(i);
1074 }
1075 chunk.insert(32, 32);
1076 let out_vec: Vec<i32> = chunk.into_iter().collect();
1077 let should_vec: Vec<i32> = (0..64).collect();
1078 assert_eq!(should_vec, out_vec);
1079 }
1080
1081 #[test]
1082 fn insert_back() {
1083 let mut chunk = Chunk::<_, U64>::new();
1084 for i in 0..63 {
1085 chunk.push_back(i);
1086 }
1087 chunk.insert(63, 63);
1088 let out_vec: Vec<i32> = chunk.into_iter().collect();
1089 let should_vec: Vec<i32> = (0..64).collect();
1090 assert_eq!(should_vec, out_vec);
1091 }
1092
1093 #[test]
1094 fn insert_front() {
1095 let mut chunk = Chunk::<_, U64>::new();
1096 for i in 1..64 {
1097 chunk.push_front(64 - i);
1098 }
1099 chunk.insert(0, 0);
1100 let out_vec: Vec<i32> = chunk.into_iter().collect();
1101 let should_vec: Vec<i32> = (0..64).collect();
1102 assert_eq!(should_vec, out_vec);
1103 }
1104
1105 #[test]
1106 fn remove_value() {
1107 let mut chunk = Chunk::<_, U64>::new();
1108 for i in 0..64 {
1109 chunk.push_back(i);
1110 }
1111 chunk.remove(32);
1112 let out_vec: Vec<i32> = chunk.into_iter().collect();
1113 let should_vec: Vec<i32> = (0..32).chain(33..64).collect();
1114 assert_eq!(should_vec, out_vec);
1115 }
1116
1117 use std::sync::atomic::{AtomicUsize, Ordering};
1118
1119 struct DropTest<'a> {
1120 counter: &'a AtomicUsize,
1121 }
1122
1123 impl<'a> DropTest<'a> {
1124 fn new(counter: &'a AtomicUsize) -> Self {
1125 counter.fetch_add(1, Ordering::Relaxed);
1126 DropTest { counter }
1127 }
1128 }
1129
1130 impl<'a> Drop for DropTest<'a> {
1131 fn drop(&mut self) {
1132 self.counter.fetch_sub(1, Ordering::Relaxed);
1133 }
1134 }
1135
1136 #[test]
1137 fn dropping() {
1138 let counter = AtomicUsize::new(0);
1139 {
1140 let mut chunk: Chunk<DropTest> = Chunk::new();
1141 for _i in 0..20 {
1142 chunk.push_back(DropTest::new(&counter))
1143 }
1144 for _i in 0..20 {
1145 chunk.push_front(DropTest::new(&counter))
1146 }
1147 assert_eq!(40, counter.load(Ordering::Relaxed));
1148 for _i in 0..10 {
1149 chunk.pop_back();
1150 }
1151 assert_eq!(30, counter.load(Ordering::Relaxed));
1152 }
1153 assert_eq!(0, counter.load(Ordering::Relaxed));
1154 }
1155 }