imbl_sized_chunks/sized_chunk/
mod.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
9use crate::inline_array::InlineArray;
10use core::borrow::{Borrow, BorrowMut};
11use core::cmp::Ordering;
12use core::fmt::{Debug, Error, Formatter};
13use core::hash::{Hash, Hasher};
14use core::iter::FromIterator;
15use core::mem::{replace, MaybeUninit};
16use core::ops::{Deref, DerefMut, Index, IndexMut};
17use core::ptr;
18use core::slice::{
19    from_raw_parts, from_raw_parts_mut, Iter as SliceIter, IterMut as SliceIterMut, SliceIndex,
20};
21
22#[cfg(feature = "std")]
23use std::io;
24
25mod iter;
26pub use self::iter::{Drain, Iter};
27
28#[cfg(feature = "refpool")]
29mod refpool;
30
31/// A fixed capacity smart array.
32///
33/// An inline array of items with a variable length but a fixed, preallocated
34/// capacity given by the `N` type.
35///
36/// It's 'smart' because it's able to reorganise its contents based on expected
37/// behaviour. If you construct one using `push_back`, it will be laid out like
38/// a `Vec` with space at the end. If you `push_front` it will start filling in
39/// values from the back instead of the front, so that you still get linear time
40/// push as long as you don't reverse direction. If you do, and there's no room
41/// at the end you're pushing to, it'll shift its contents over to the other
42/// side, creating more space to push into. This technique is tuned for
43/// `Chunk`'s expected use case in [im::Vector]: usually, chunks always see
44/// either `push_front` or `push_back`, but not both unless they move around
45/// inside the tree, in which case they're able to reorganise themselves with
46/// reasonable efficiency to suit their new usage patterns.
47///
48/// It maintains a `left` index and a `right` index instead of a simple length
49/// counter in order to accomplish this, much like a ring buffer would, except
50/// that the `Chunk` keeps all its items sequentially in memory so that you can
51/// always get a `&[A]` slice for them, at the price of the occasional
52/// reordering operation. The allocated size of a `Chunk` is thus `usize` * 2 +
53/// `A` * `N`.
54///
55/// This technique also lets us choose to shift the shortest side to account for
56/// the inserted or removed element when performing insert and remove
57/// operations, unlike `Vec` where you always need to shift the right hand side.
58///
59/// Unlike a `Vec`, the `Chunk` has a fixed capacity and cannot grow beyond it.
60/// Being intended for low level use, it expects you to know or test whether
61/// you're pushing to a full array, and has an API more geared towards panics
62/// than returning `Option`s, on the assumption that you know what you're doing.
63/// Of course, if you don't, you can expect it to panic immediately rather than
64/// do something undefined and usually bad.
65///
66/// ## Isn't this just a less efficient ring buffer?
67///
68/// You might be wondering why you would want to use this data structure rather
69/// than a [`RingBuffer`][RingBuffer], which is similar but doesn't need to
70/// shift its content around when it hits the sides of the allocated buffer. The
71/// answer is that `Chunk` can be dereferenced into a slice, while a ring buffer
72/// can not. You'll also save a few cycles on index lookups, as a `Chunk`'s data
73/// is guaranteed to be contiguous in memory, so there's no need to remap logical
74/// indices to a ring buffer's physical layout.
75///
76/// # Examples
77///
78/// ```rust
79/// # use imbl_sized_chunks::Chunk;
80/// // Construct a chunk with a 64 item capacity
81/// let mut chunk = Chunk::<i32, 64>::new();
82/// // Fill it with descending numbers
83/// chunk.extend((0..64).rev());
84/// // It derefs to a slice so we can use standard slice methods
85/// chunk.sort();
86/// // It's got all the amenities like `FromIterator` and `Eq`
87/// let expected: Chunk<i32, 64> = (0..64).collect();
88/// assert_eq!(expected, chunk);
89/// ```
90///
91/// [im::Vector]: https://docs.rs/im/latest/im/vector/enum.Vector.html
92/// [RingBuffer]: ../ring_buffer/struct.RingBuffer.html
93pub struct Chunk<A, const N: usize> {
94    left: usize,
95    right: usize,
96    data: MaybeUninit<[A; N]>,
97}
98
99impl<A, const N: usize> Drop for Chunk<A, N> {
100    fn drop(&mut self) {
101        unsafe { ptr::drop_in_place(self.as_mut_slice()) }
102    }
103}
104
105impl<A, const N: usize> Clone for Chunk<A, N>
106where
107    A: Clone,
108{
109    fn clone(&self) -> Self {
110        let mut out = Self::new();
111        out.left = self.left;
112        out.right = self.left;
113        for index in self.left..self.right {
114            unsafe { Chunk::force_write(index, (*self.ptr(index)).clone(), &mut out) }
115            // Panic safety, move the right index to cover only the really initialized things. This
116            // way we don't try to drop uninitialized, but also don't leak if we panic in the
117            // middle.
118            out.right = index + 1;
119        }
120        out
121    }
122}
123
124impl<A, const N: usize> Chunk<A, N> {
125    /// The maximum number of elements this `Chunk` can contain.
126    pub const CAPACITY: usize = N;
127
128    /// Construct a new empty chunk.
129    pub fn new() -> Self {
130        Self {
131            left: 0,
132            right: 0,
133            data: MaybeUninit::uninit(),
134        }
135    }
136
137    /// Construct a new chunk with one item.
138    pub fn unit(value: A) -> Self {
139        assert!(Self::CAPACITY >= 1);
140        let mut chunk = Self {
141            left: 0,
142            right: 1,
143            data: MaybeUninit::uninit(),
144        };
145        unsafe {
146            Chunk::force_write(0, value, &mut chunk);
147        }
148        chunk
149    }
150
151    /// Construct a new chunk with two items.
152    pub fn pair(left: A, right: A) -> Self {
153        assert!(Self::CAPACITY >= 2);
154        let mut chunk = Self {
155            left: 0,
156            right: 2,
157            data: MaybeUninit::uninit(),
158        };
159        unsafe {
160            Chunk::force_write(0, left, &mut chunk);
161            Chunk::force_write(1, right, &mut chunk);
162        }
163        chunk
164    }
165
166    /// Construct a new chunk and move every item from `other` into the new
167    /// chunk.
168    ///
169    /// Time: O(n)
170    pub fn drain_from(other: &mut Self) -> Self {
171        let other_len = other.len();
172        Self::from_front(other, other_len)
173    }
174
175    /// Construct a new chunk and populate it by taking `count` items from the
176    /// iterator `iter`.
177    ///
178    /// Panics if the iterator contains less than `count` items.
179    ///
180    /// Time: O(n)
181    pub fn collect_from<I>(iter: &mut I, mut count: usize) -> Self
182    where
183        I: Iterator<Item = A>,
184    {
185        let mut chunk = Self::new();
186        while count > 0 {
187            count -= 1;
188            chunk.push_back(
189                iter.next()
190                    .expect("Chunk::collect_from: underfull iterator"),
191            );
192        }
193        chunk
194    }
195
196    /// Construct a new chunk and populate it by taking `count` items from the
197    /// front of `other`.
198    ///
199    /// Time: O(n) for the number of items moved
200    pub fn from_front(other: &mut Self, count: usize) -> Self {
201        let other_len = other.len();
202        debug_assert!(count <= other_len);
203        let mut chunk = Self::new();
204        unsafe { Chunk::force_copy_to(other.left, 0, count, other, &mut chunk) };
205        chunk.right = count;
206        other.left += count;
207        chunk
208    }
209
210    /// Construct a new chunk and populate it by taking `count` items from the
211    /// back of `other`.
212    ///
213    /// Time: O(n) for the number of items moved
214    pub fn from_back(other: &mut Self, count: usize) -> Self {
215        let other_len = other.len();
216        debug_assert!(count <= other_len);
217        let mut chunk = Self::new();
218        unsafe { Chunk::force_copy_to(other.right - count, 0, count, other, &mut chunk) };
219        chunk.right = count;
220        other.right -= count;
221        chunk
222    }
223
224    /// Get the length of the chunk.
225    #[inline]
226    pub fn len(&self) -> usize {
227        self.right - self.left
228    }
229
230    /// Test if the chunk is empty.
231    #[inline]
232    pub fn is_empty(&self) -> bool {
233        self.left == self.right
234    }
235
236    /// Test if the chunk is at capacity.
237    #[inline]
238    pub fn is_full(&self) -> bool {
239        self.left == 0 && self.right == Self::CAPACITY
240    }
241
242    #[inline]
243    unsafe fn ptr(&self, index: usize) -> *const A {
244        unsafe { (&self.data as *const _ as *const A).add(index) }
245    }
246
247    /// It has no bounds checks
248    #[inline]
249    unsafe fn mut_ptr(&mut self, index: usize) -> *mut A {
250        unsafe { (&mut self.data as *mut _ as *mut A).add(index) }
251    }
252
253    /// Copy the value at an index, discarding ownership of the copied value
254    #[inline]
255    unsafe fn force_read(index: usize, chunk: &mut Self) -> A {
256        unsafe { chunk.ptr(index).read() }
257    }
258
259    /// Write a value at an index without trying to drop what's already there.
260    /// It has no bounds checks.
261    #[inline]
262    unsafe fn force_write(index: usize, value: A, chunk: &mut Self) {
263        unsafe { chunk.mut_ptr(index).write(value) }
264    }
265
266    /// Copy a range within a chunk
267    #[inline]
268    unsafe fn force_copy(from: usize, to: usize, count: usize, chunk: &mut Self) {
269        if count > 0 {
270            let data = &mut chunk.data as *mut _ as *mut A;
271            unsafe {
272                let from = data.add(from);
273                let to = data.add(to);
274                ptr::copy(from, to, count)
275            }
276        }
277    }
278
279    /// Write values from iterator into range starting at write_index.
280    ///
281    /// Will overwrite values at the relevant range without dropping even in case the values were
282    /// already initialized (it is expected they are empty). Does not update the left or right
283    /// index.
284    ///
285    /// # Safety
286    ///
287    /// Range checks must already have been performed.
288    ///
289    /// # Panics
290    ///
291    /// If the iterator panics, the chunk becomes conceptually empty and will leak any previous
292    /// elements (even the ones outside the range).
293    #[inline]
294    unsafe fn write_from_iter<I>(mut write_index: usize, iter: I, chunk: &mut Self)
295    where
296        I: ExactSizeIterator<Item = A>,
297    {
298        // Panic safety. We make the array conceptually empty, so we never ever drop anything that
299        // is unitialized. We do so because we expect to be called when there's a potential "hole"
300        // in the array that makes the space for the new elements to be written. We return it back
301        // to original when everything goes fine, but leak any elements on panic. This is bad, but
302        // better than dropping non-existing stuff.
303        //
304        // Should we worry about some better panic recovery than this?
305        let left = replace(&mut chunk.left, 0);
306        let right = replace(&mut chunk.right, 0);
307        let len = iter.len();
308        let expected_end = write_index + len;
309        for value in iter.take(len) {
310            unsafe {
311                Chunk::force_write(write_index, value, chunk);
312            }
313            write_index += 1;
314        }
315        // Oops, we have a hole in here now. That would be bad, give up.
316        assert_eq!(
317            expected_end, write_index,
318            "ExactSizeIterator yielded fewer values than advertised",
319        );
320        chunk.left = left;
321        chunk.right = right;
322    }
323
324    /// Copy a range between chunks
325    #[inline]
326    unsafe fn force_copy_to(
327        from: usize,
328        to: usize,
329        count: usize,
330        chunk: &mut Self,
331        other: &mut Self,
332    ) {
333        if count > 0 {
334            unsafe { ptr::copy_nonoverlapping(chunk.ptr(from), other.mut_ptr(to), count) }
335        }
336    }
337
338    /// Push an item to the front of the chunk.
339    ///
340    /// Panics if the capacity of the chunk is exceeded.
341    ///
342    /// Time: O(1) if there's room at the front, O(n) otherwise
343    pub fn push_front(&mut self, value: A) {
344        if self.is_full() {
345            panic!("Chunk::push_front: can't push to full chunk");
346        }
347        if self.is_empty() {
348            self.left = N;
349            self.right = N;
350        } else if self.left == 0 {
351            self.left = N - self.right;
352            unsafe { Chunk::force_copy(0, self.left, self.right, self) };
353            self.right = N;
354        }
355        self.left -= 1;
356        unsafe { Chunk::force_write(self.left, value, self) }
357    }
358
359    /// Push an item to the back of the chunk.
360    ///
361    /// Panics if the capacity of the chunk is exceeded.
362    ///
363    /// Time: O(1) if there's room at the back, O(n) otherwise
364    pub fn push_back(&mut self, value: A) {
365        if self.is_full() {
366            panic!("Chunk::push_back: can't push to full chunk");
367        }
368        if self.is_empty() {
369            self.left = 0;
370            self.right = 0;
371        } else if self.right == N {
372            unsafe { Chunk::force_copy(self.left, 0, self.len(), self) };
373            self.right = N - self.left;
374            self.left = 0;
375        }
376        unsafe { Chunk::force_write(self.right, value, self) }
377        self.right += 1;
378    }
379
380    /// Pop an item off the front of the chunk.
381    ///
382    /// Panics if the chunk is empty.
383    ///
384    /// Time: O(1)
385    pub fn pop_front(&mut self) -> A {
386        if self.is_empty() {
387            panic!("Chunk::pop_front: can't pop from empty chunk");
388        } else {
389            let value = unsafe { Chunk::force_read(self.left, self) };
390            self.left += 1;
391            value
392        }
393    }
394
395    /// Pop an item off the back of the chunk.
396    ///
397    /// Panics if the chunk is empty.
398    ///
399    /// Time: O(1)
400    pub fn pop_back(&mut self) -> A {
401        if self.is_empty() {
402            panic!("Chunk::pop_back: can't pop from empty chunk");
403        } else {
404            self.right -= 1;
405            unsafe { Chunk::force_read(self.right, self) }
406        }
407    }
408
409    /// Discard all items up to but not including `index`.
410    ///
411    /// Panics if `index` is out of bounds.
412    ///
413    /// Time: O(n) for the number of items dropped
414    pub fn drop_left(&mut self, index: usize) {
415        if index > 0 {
416            unsafe { ptr::drop_in_place(&mut self[..index]) }
417            self.left += index;
418        }
419    }
420
421    /// Discard all items from `index` onward.
422    ///
423    /// Panics if `index` is out of bounds.
424    ///
425    /// Time: O(n) for the number of items dropped
426    pub fn drop_right(&mut self, index: usize) {
427        if index != self.len() {
428            unsafe { ptr::drop_in_place(&mut self[index..]) }
429            self.right = self.left + index;
430        }
431    }
432
433    /// Split a chunk into two, the original chunk containing
434    /// everything up to `index` and the returned chunk containing
435    /// everything from `index` onwards.
436    ///
437    /// Panics if `index` is out of bounds.
438    ///
439    /// Time: O(n) for the number of items in the new chunk
440    pub fn split_off(&mut self, index: usize) -> Self {
441        if index > self.len() {
442            panic!("Chunk::split_off: index out of bounds");
443        }
444        if index == self.len() {
445            return Self::new();
446        }
447        let mut right_chunk = Self::new();
448        let start = self.left + index;
449        let len = self.right - start;
450        unsafe { Chunk::force_copy_to(start, 0, len, self, &mut right_chunk) };
451        right_chunk.right = len;
452        self.right = start;
453        right_chunk
454    }
455
456    /// Remove all items from `other` and append them to the back of `self`.
457    ///
458    /// Panics if the capacity of the chunk is exceeded.
459    ///
460    /// Time: O(n) for the number of items moved
461    pub fn append(&mut self, other: &mut Self) {
462        let self_len = self.len();
463        let other_len = other.len();
464        if self_len + other_len > N {
465            panic!("Chunk::append: chunk size overflow");
466        }
467        if self.right + other_len > N {
468            unsafe { Chunk::force_copy(self.left, 0, self_len, self) };
469            self.right -= self.left;
470            self.left = 0;
471        }
472        unsafe { Chunk::force_copy_to(other.left, self.right, other_len, other, self) };
473        self.right += other_len;
474        other.left = 0;
475        other.right = 0;
476    }
477
478    /// Remove `count` items from the front of `other` and append them to the
479    /// back of `self`.
480    ///
481    /// Panics if `self` doesn't have `count` items left, or if `other` has
482    /// fewer than `count` items.
483    ///
484    /// Time: O(n) for the number of items moved
485    pub fn drain_from_front(&mut self, other: &mut Self, count: usize) {
486        let self_len = self.len();
487        let other_len = other.len();
488        assert!(self_len + count <= N);
489        assert!(other_len >= count);
490        if self.right + count > N {
491            unsafe { Chunk::force_copy(self.left, 0, self_len, self) };
492            self.right -= self.left;
493            self.left = 0;
494        }
495        unsafe { Chunk::force_copy_to(other.left, self.right, count, other, self) };
496        self.right += count;
497        other.left += count;
498    }
499
500    /// Remove `count` items from the back of `other` and append them to the
501    /// front of `self`.
502    ///
503    /// Panics if `self` doesn't have `count` items left, or if `other` has
504    /// fewer than `count` items.
505    ///
506    /// Time: O(n) for the number of items moved
507    pub fn drain_from_back(&mut self, other: &mut Self, count: usize) {
508        let self_len = self.len();
509        let other_len = other.len();
510        assert!(self_len + count <= N);
511        assert!(other_len >= count);
512        if self.left < count {
513            unsafe { Chunk::force_copy(self.left, N - self_len, self_len, self) };
514            self.left = N - self_len;
515            self.right = N;
516        }
517        unsafe { Chunk::force_copy_to(other.right - count, self.left - count, count, other, self) };
518        self.left -= count;
519        other.right -= count;
520    }
521
522    /// Update the value at index `index`, returning the old value.
523    ///
524    /// Panics if `index` is out of bounds.
525    ///
526    /// Time: O(1)
527    pub fn set(&mut self, index: usize, value: A) -> A {
528        replace(&mut self[index], value)
529    }
530
531    /// Insert a new value at index `index`, shifting all the following values
532    /// to the right.
533    ///
534    /// Panics if the index is out of bounds or the chunk is full.
535    ///
536    /// Time: O(n) for the number of elements shifted
537    pub fn insert(&mut self, index: usize, value: A) {
538        if self.is_full() {
539            panic!("Chunk::insert: chunk is full");
540        }
541        if index > self.len() {
542            panic!("Chunk::insert: index out of bounds");
543        }
544        let real_index = index + self.left;
545        let left_size = index;
546        let right_size = self.right - real_index;
547        if self.right == N || (self.left > 0 && left_size < right_size) {
548            unsafe {
549                Chunk::force_copy(self.left, self.left - 1, left_size, self);
550                Chunk::force_write(real_index - 1, value, self);
551            }
552            self.left -= 1;
553        } else {
554            unsafe {
555                Chunk::force_copy(real_index, real_index + 1, right_size, self);
556                Chunk::force_write(real_index, value, self);
557            }
558            self.right += 1;
559        }
560    }
561
562    /// Insert a new value into the chunk in sorted order.
563    ///
564    /// This assumes every element of the chunk is already in sorted order.
565    /// If not, the value will still be inserted but the ordering is not
566    /// guaranteed.
567    ///
568    /// Time: O(log n) to find the insert position, then O(n) for the number
569    /// of elements shifted.
570    ///
571    /// # Examples
572    ///
573    /// ```rust
574    /// # use std::iter::FromIterator;
575    /// # use imbl_sized_chunks::Chunk;
576    /// let mut chunk = Chunk::<i32, 64>::from_iter(0..5);
577    /// chunk.insert_ordered(3);
578    /// assert_eq!(&[0, 1, 2, 3, 3, 4], chunk.as_slice());
579    /// ```
580    pub fn insert_ordered(&mut self, value: A)
581    where
582        A: Ord,
583    {
584        if self.is_full() {
585            panic!("Chunk::insert: chunk is full");
586        }
587        match self.binary_search(&value) {
588            Ok(index) => self.insert(index, value),
589            Err(index) => self.insert(index, value),
590        }
591    }
592
593    /// Insert multiple values at index `index`, shifting all the following values
594    /// to the right.
595    ///
596    /// Panics if the index is out of bounds or the chunk doesn't have room for
597    /// all the values.
598    ///
599    /// Time: O(m+n) where m is the number of elements inserted and n is the number
600    /// of elements following the insertion index. Calling `insert`
601    /// repeatedly would be O(m*n).
602    pub fn insert_from<Iterable, I>(&mut self, index: usize, iter: Iterable)
603    where
604        Iterable: IntoIterator<Item = A, IntoIter = I>,
605        I: ExactSizeIterator<Item = A>,
606    {
607        let iter = iter.into_iter();
608        let insert_size = iter.len();
609        if self.len() + insert_size > Self::CAPACITY {
610            panic!(
611                "Chunk::insert_from: chunk cannot fit {} elements",
612                insert_size
613            );
614        }
615        if index > self.len() {
616            panic!("Chunk::insert_from: index out of bounds");
617        }
618        let real_index = index + self.left;
619        let left_size = index;
620        let right_size = self.right - real_index;
621        if self.right == N || (self.left >= insert_size && left_size < right_size) {
622            unsafe {
623                Chunk::force_copy(self.left, self.left - insert_size, left_size, self);
624                let write_index = real_index - insert_size;
625                Chunk::write_from_iter(write_index, iter, self);
626            }
627            self.left -= insert_size;
628        } else if self.left == 0 || (self.right + insert_size <= Self::CAPACITY) {
629            unsafe {
630                Chunk::force_copy(real_index, real_index + insert_size, right_size, self);
631                let write_index = real_index;
632                Chunk::write_from_iter(write_index, iter, self);
633            }
634            self.right += insert_size;
635        } else {
636            unsafe {
637                Chunk::force_copy(self.left, 0, left_size, self);
638                Chunk::force_copy(real_index, left_size + insert_size, right_size, self);
639                let write_index = left_size;
640                Chunk::write_from_iter(write_index, iter, self);
641            }
642            self.right -= self.left;
643            self.right += insert_size;
644            self.left = 0;
645        }
646    }
647
648    /// Remove the value at index `index`, shifting all the following values to
649    /// the left.
650    ///
651    /// Returns the removed value.
652    ///
653    /// Panics if the index is out of bounds.
654    ///
655    /// Time: O(n) for the number of items shifted
656    pub fn remove(&mut self, index: usize) -> A {
657        if index >= self.len() {
658            panic!("Chunk::remove: index out of bounds");
659        }
660        let real_index = index + self.left;
661        let value = unsafe { Chunk::force_read(real_index, self) };
662        let left_size = index;
663        let right_size = self.right - real_index - 1;
664        if left_size < right_size {
665            unsafe { Chunk::force_copy(self.left, self.left + 1, left_size, self) };
666            self.left += 1;
667        } else {
668            unsafe { Chunk::force_copy(real_index + 1, real_index, right_size, self) };
669            self.right -= 1;
670        }
671        value
672    }
673
674    /// Construct an iterator that drains values from the front of the chunk.
675    pub fn drain(&mut self) -> Drain<'_, A, N> {
676        Drain { chunk: self }
677    }
678
679    /// Discard the contents of the chunk.
680    ///
681    /// Time: O(n)
682    pub fn clear(&mut self) {
683        unsafe { ptr::drop_in_place(self.as_mut_slice()) }
684        self.left = 0;
685        self.right = 0;
686    }
687
688    /// Get a reference to the contents of the chunk as a slice.
689    pub fn as_slice(&self) -> &[A] {
690        unsafe {
691            from_raw_parts(
692                (&self.data as *const MaybeUninit<[A; N]> as *const A).add(self.left),
693                self.len(),
694            )
695        }
696    }
697
698    /// Get a reference to the contents of the chunk as a mutable slice.
699    pub fn as_mut_slice(&mut self) -> &mut [A] {
700        unsafe {
701            from_raw_parts_mut(
702                (&mut self.data as *mut MaybeUninit<[A; N]> as *mut A).add(self.left),
703                self.len(),
704            )
705        }
706    }
707
708    /// Get a pointer to the contents of the chunk as a slice
709    ///
710    /// # Safety
711    ///
712    /// The provided chunk pointer must be dereferencable
713    pub unsafe fn as_mut_slice_ptr(this: *mut Self) -> *mut [A] {
714        unsafe {
715            // Manual `len` to prevent creating a reference
716            let len = (*this).right - (*this).left;
717            ptr::slice_from_raw_parts_mut(ptr::addr_of_mut!((*this).data).cast(), len)
718        }
719    }
720}
721
722impl<A, const N: usize> Default for Chunk<A, N> {
723    fn default() -> Self {
724        Self::new()
725    }
726}
727
728impl<A, I, const N: usize> Index<I> for Chunk<A, N>
729where
730    I: SliceIndex<[A]>,
731{
732    type Output = I::Output;
733    fn index(&self, index: I) -> &Self::Output {
734        self.as_slice().index(index)
735    }
736}
737
738impl<A, I, const N: usize> IndexMut<I> for Chunk<A, N>
739where
740    I: SliceIndex<[A]>,
741{
742    fn index_mut(&mut self, index: I) -> &mut Self::Output {
743        self.as_mut_slice().index_mut(index)
744    }
745}
746
747impl<A, const N: usize> Debug for Chunk<A, N>
748where
749    A: Debug,
750{
751    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
752        f.write_str("Chunk")?;
753        f.debug_list().entries(self.iter()).finish()
754    }
755}
756
757impl<A, const N: usize> Hash for Chunk<A, N>
758where
759    A: Hash,
760{
761    fn hash<H>(&self, hasher: &mut H)
762    where
763        H: Hasher,
764    {
765        for item in self {
766            item.hash(hasher)
767        }
768    }
769}
770
771impl<A, Slice, const N: usize> PartialEq<Slice> for Chunk<A, N>
772where
773    Slice: Borrow<[A]>,
774    A: PartialEq,
775{
776    fn eq(&self, other: &Slice) -> bool {
777        self.as_slice() == other.borrow()
778    }
779}
780
781impl<A, const N: usize> Eq for Chunk<A, N> where A: Eq {}
782
783impl<A, const N: usize> PartialOrd for Chunk<A, N>
784where
785    A: PartialOrd,
786{
787    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
788        self.iter().partial_cmp(other.iter())
789    }
790}
791
792impl<A, const N: usize> Ord for Chunk<A, N>
793where
794    A: Ord,
795{
796    fn cmp(&self, other: &Self) -> Ordering {
797        self.iter().cmp(other.iter())
798    }
799}
800
801#[cfg(feature = "std")]
802impl<const N: usize> io::Write for Chunk<u8, N> {
803    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
804        let old_len = self.len();
805        self.extend(buf.iter().cloned().take(N - old_len));
806        Ok(self.len() - old_len)
807    }
808
809    fn flush(&mut self) -> io::Result<()> {
810        Ok(())
811    }
812}
813
814#[cfg(feature = "std")]
815impl<const N: usize> std::io::Read for Chunk<u8, N> {
816    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
817        let read_size = buf.len().min(self.len());
818        if read_size == 0 {
819            Ok(0)
820        } else {
821            for p in buf.iter_mut().take(read_size) {
822                *p = self.pop_front();
823            }
824            Ok(read_size)
825        }
826    }
827}
828
829impl<A, T, const N: usize> From<InlineArray<A, T>> for Chunk<A, N> {
830    #[inline]
831    fn from(mut array: InlineArray<A, T>) -> Self {
832        Self::from(&mut array)
833    }
834}
835
836impl<A, T, const N: usize> From<&mut InlineArray<A, T>> for Chunk<A, N> {
837    fn from(array: &mut InlineArray<A, T>) -> Self {
838        // The first capacity comparison is to help optimize it out
839        assert!(
840            InlineArray::<A, T>::CAPACITY <= Self::CAPACITY || array.len() <= Self::CAPACITY,
841            "CAPACITY too small"
842        );
843        let mut out = Self::new();
844        out.left = 0;
845        out.right = array.len();
846        unsafe {
847            ptr::copy_nonoverlapping(array.data(), out.mut_ptr(0), out.right);
848            *array.len_mut() = 0;
849        }
850        out
851    }
852}
853
854impl<A, const N: usize> Borrow<[A]> for Chunk<A, N> {
855    fn borrow(&self) -> &[A] {
856        self.as_slice()
857    }
858}
859
860impl<A, const N: usize> BorrowMut<[A]> for Chunk<A, N> {
861    fn borrow_mut(&mut self) -> &mut [A] {
862        self.as_mut_slice()
863    }
864}
865
866impl<A, const N: usize> AsRef<[A]> for Chunk<A, N> {
867    fn as_ref(&self) -> &[A] {
868        self.as_slice()
869    }
870}
871
872impl<A, const N: usize> AsMut<[A]> for Chunk<A, N> {
873    fn as_mut(&mut self) -> &mut [A] {
874        self.as_mut_slice()
875    }
876}
877
878impl<A, const N: usize> Deref for Chunk<A, N> {
879    type Target = [A];
880
881    fn deref(&self) -> &Self::Target {
882        self.as_slice()
883    }
884}
885
886impl<A, const N: usize> DerefMut for Chunk<A, N> {
887    fn deref_mut(&mut self) -> &mut Self::Target {
888        self.as_mut_slice()
889    }
890}
891
892impl<A, const N: usize> FromIterator<A> for Chunk<A, N> {
893    fn from_iter<I>(it: I) -> Self
894    where
895        I: IntoIterator<Item = A>,
896    {
897        let mut chunk = Self::new();
898        for item in it {
899            chunk.push_back(item);
900        }
901        chunk
902    }
903}
904
905impl<'a, A, const N: usize> IntoIterator for &'a Chunk<A, N> {
906    type Item = &'a A;
907    type IntoIter = SliceIter<'a, A>;
908    fn into_iter(self) -> Self::IntoIter {
909        self.iter()
910    }
911}
912
913impl<'a, A, const N: usize> IntoIterator for &'a mut Chunk<A, N> {
914    type Item = &'a mut A;
915    type IntoIter = SliceIterMut<'a, A>;
916    fn into_iter(self) -> Self::IntoIter {
917        self.iter_mut()
918    }
919}
920
921impl<A, const N: usize> Extend<A> for Chunk<A, N> {
922    /// Append the contents of the iterator to the back of the chunk.
923    ///
924    /// Panics if the chunk exceeds its capacity.
925    ///
926    /// Time: O(n) for the length of the iterator
927    fn extend<I>(&mut self, it: I)
928    where
929        I: IntoIterator<Item = A>,
930    {
931        for item in it {
932            self.push_back(item);
933        }
934    }
935}
936
937impl<'a, A, const N: usize> Extend<&'a A> for Chunk<A, N>
938where
939    A: 'a + Copy,
940{
941    /// Append the contents of the iterator to the back of the chunk.
942    ///
943    /// Panics if the chunk exceeds its capacity.
944    ///
945    /// Time: O(n) for the length of the iterator
946    fn extend<I>(&mut self, it: I)
947    where
948        I: IntoIterator<Item = &'a A>,
949    {
950        for item in it {
951            self.push_back(*item);
952        }
953    }
954}
955
956impl<A, const N: usize> IntoIterator for Chunk<A, N> {
957    type Item = A;
958    type IntoIter = Iter<A, N>;
959
960    fn into_iter(self) -> Self::IntoIter {
961        Iter { chunk: self }
962    }
963}
964
965#[cfg(test)]
966#[rustfmt::skip]
967mod test {
968    use super::*;
969
970    #[test]
971    #[should_panic(expected = "Chunk::push_back: can't push to full chunk")]
972    fn issue_11_testcase1d() {
973        let mut chunk = Chunk::<usize, 2>::pair(123, 456);
974        chunk.push_back(789);
975    }
976
977    #[test]
978    #[should_panic(expected = "CAPACITY too small")]
979    fn issue_11_testcase2a() {
980        let mut from = InlineArray::<u8, [u8; 256]>::new();
981        from.push(1);
982
983        let _ = Chunk::<u8, 0>::from(from);
984    }
985
986    #[test]
987    fn issue_11_testcase2b() {
988        let mut from = InlineArray::<u8, [u8; 256]>::new();
989        from.push(1);
990
991        let _ = Chunk::<u8, 1>::from(from);
992    }
993
994    struct DropDetector(u32);
995
996    impl DropDetector {
997        fn new(num: u32) -> Self {
998            DropDetector(num)
999        }
1000    }
1001
1002    impl Drop for DropDetector {
1003        fn drop(&mut self) {
1004            assert!(self.0 == 42 || self.0 == 43);
1005        }
1006    }
1007
1008    impl Clone for DropDetector {
1009        fn clone(&self) -> Self {
1010            if self.0 == 42 {
1011                panic!("panic on clone")
1012            }
1013            DropDetector::new(self.0)
1014        }
1015    }
1016
1017    /// This is for miri to catch
1018    #[test]
1019    fn issue_11_testcase3a() {
1020        let mut chunk = Chunk::<DropDetector, 3>::new();
1021        chunk.push_back(DropDetector::new(42));
1022        chunk.push_back(DropDetector::new(42));
1023        chunk.push_back(DropDetector::new(43));
1024        let _ = chunk.pop_front();
1025
1026        let _ = std::panic::catch_unwind(|| {
1027            let _ = chunk.clone();
1028        });
1029    }
1030
1031    struct PanickingIterator {
1032        current: u32,
1033        panic_at: u32,
1034        len: usize,
1035    }
1036
1037    impl Iterator for PanickingIterator {
1038        type Item = DropDetector;
1039
1040        fn next(&mut self) -> Option<Self::Item> {
1041            let num = self.current;
1042
1043            if num == self.panic_at {
1044                panic!("panicking index")
1045            }
1046
1047            self.current += 1;
1048            Some(DropDetector::new(num))
1049        }
1050
1051        fn size_hint(&self) -> (usize, Option<usize>) {
1052            (self.len, Some(self.len))
1053        }
1054    }
1055
1056    impl ExactSizeIterator for PanickingIterator {}
1057
1058    #[test]
1059    fn issue_11_testcase3b() {
1060        let _ = std::panic::catch_unwind(|| {
1061            let mut chunk = Chunk::<DropDetector, 5>::new();
1062            chunk.push_back(DropDetector::new(1));
1063            chunk.push_back(DropDetector::new(2));
1064            chunk.push_back(DropDetector::new(3));
1065
1066            chunk.insert_from(
1067                1,
1068                PanickingIterator {
1069                    current: 1,
1070                    panic_at: 1,
1071                    len: 1,
1072                },
1073            );
1074        });
1075    }
1076
1077    struct FakeSizeIterator { reported: usize, actual: usize }
1078    impl Iterator for FakeSizeIterator {
1079        type Item = u8;
1080        fn next(&mut self) -> Option<Self::Item> {
1081            if self.actual == 0 {
1082                None
1083            } else {
1084                self.actual -= 1;
1085                Some(1)
1086            }
1087        }
1088
1089        fn size_hint(&self) -> (usize, Option<usize>) {
1090            (self.reported, Some(self.reported))
1091        }
1092    }
1093
1094    impl ExactSizeIterator for FakeSizeIterator {
1095        fn len(&self) -> usize {
1096            self.reported
1097        }
1098    }
1099
1100    #[test]
1101    fn iterator_too_long() {
1102        let mut chunk = Chunk::<u8, 5>::new();
1103        chunk.push_back(0);
1104        chunk.push_back(1);
1105        chunk.push_back(2);
1106        chunk.insert_from(1, FakeSizeIterator { reported: 1, actual: 10 });
1107
1108        let mut chunk = Chunk::<u8, 5>::new();
1109        chunk.push_back(1);
1110        chunk.insert_from(0, FakeSizeIterator { reported: 1, actual: 10 });
1111
1112        let mut chunk = Chunk::<u8, 5>::new();
1113        chunk.insert_from(0, FakeSizeIterator { reported: 1, actual: 10 });
1114    }
1115
1116    #[test]
1117    #[should_panic(expected = "ExactSizeIterator yielded fewer values than advertised")]
1118    fn iterator_too_short1() {
1119        let mut chunk = Chunk::<u8, 5>::new();
1120        chunk.push_back(0);
1121        chunk.push_back(1);
1122        chunk.push_back(2);
1123        chunk.insert_from(1, FakeSizeIterator { reported: 2, actual: 0 });
1124    }
1125
1126    #[test]
1127    #[should_panic(expected = "ExactSizeIterator yielded fewer values than advertised")]
1128    fn iterator_too_short2() {
1129        let mut chunk = Chunk::<u8, 5>::new();
1130        chunk.push_back(1);
1131        chunk.insert_from(1, FakeSizeIterator { reported: 4, actual: 2 });
1132    }
1133
1134    #[test]
1135    fn is_full() {
1136        let mut chunk = Chunk::<_, 64>::new();
1137        for i in 0..64 {
1138            assert!(!chunk.is_full());
1139            chunk.push_back(i);
1140        }
1141        assert!(chunk.is_full());
1142    }
1143
1144    #[test]
1145    fn push_back_front() {
1146        let mut chunk = Chunk::<_, 64>::new();
1147        for i in 12..20 {
1148            chunk.push_back(i);
1149        }
1150        assert_eq!(8, chunk.len());
1151        for i in (0..12).rev() {
1152            chunk.push_front(i);
1153        }
1154        assert_eq!(20, chunk.len());
1155        for i in 20..32 {
1156            chunk.push_back(i);
1157        }
1158        assert_eq!(32, chunk.len());
1159        let right: Vec<i32> = chunk.into_iter().collect();
1160        let left: Vec<i32> = (0..32).collect();
1161        assert_eq!(left, right);
1162    }
1163
1164    #[test]
1165    fn push_and_pop() {
1166        let mut chunk = Chunk::<_, 64>::new();
1167        for i in 0..64 {
1168            chunk.push_back(i);
1169        }
1170        for i in 0..64 {
1171            assert_eq!(i, chunk.pop_front());
1172        }
1173        for i in 0..64 {
1174            chunk.push_front(i);
1175        }
1176        for i in 0..64 {
1177            assert_eq!(i, chunk.pop_back());
1178        }
1179    }
1180
1181    #[test]
1182    fn drop_left() {
1183        let mut chunk = Chunk::<_, 64>::new();
1184        for i in 0..6 {
1185            chunk.push_back(i);
1186        }
1187        chunk.drop_left(3);
1188        let vec: Vec<i32> = chunk.into_iter().collect();
1189        assert_eq!(vec![3, 4, 5], vec);
1190    }
1191
1192    #[test]
1193    fn drop_right() {
1194        let mut chunk = Chunk::<_, 64>::new();
1195        for i in 0..6 {
1196            chunk.push_back(i);
1197        }
1198        chunk.drop_right(3);
1199        let vec: Vec<i32> = chunk.into_iter().collect();
1200        assert_eq!(vec![0, 1, 2], vec);
1201    }
1202
1203    #[test]
1204    fn split_off() {
1205        let mut left = Chunk::<_, 64>::new();
1206        for i in 0..6 {
1207            left.push_back(i);
1208        }
1209        let right = left.split_off(3);
1210        let left_vec: Vec<i32> = left.into_iter().collect();
1211        let right_vec: Vec<i32> = right.into_iter().collect();
1212        assert_eq!(vec![0, 1, 2], left_vec);
1213        assert_eq!(vec![3, 4, 5], right_vec);
1214    }
1215
1216    #[test]
1217    fn append() {
1218        let mut left = Chunk::<_, 64>::new();
1219        for i in 0..32 {
1220            left.push_back(i);
1221        }
1222        let mut right = Chunk::<_, 64>::new();
1223        for i in (32..64).rev() {
1224            right.push_front(i);
1225        }
1226        left.append(&mut right);
1227        let out_vec: Vec<i32> = left.into_iter().collect();
1228        let should_vec: Vec<i32> = (0..64).collect();
1229        assert_eq!(should_vec, out_vec);
1230    }
1231
1232    #[test]
1233    fn ref_iter() {
1234        let mut chunk = Chunk::<_, 64>::new();
1235        for i in 0..64 {
1236            chunk.push_back(i);
1237        }
1238        let out_vec: Vec<&i32> = chunk.iter().collect();
1239        let should_vec_p: Vec<i32> = (0..64).collect();
1240        let should_vec: Vec<&i32> = should_vec_p.iter().collect();
1241        assert_eq!(should_vec, out_vec);
1242    }
1243
1244    #[test]
1245    fn mut_ref_iter() {
1246        let mut chunk = Chunk::<_, 64>::new();
1247        for i in 0..64 {
1248            chunk.push_back(i);
1249        }
1250        let out_vec: Vec<&mut i32> = chunk.iter_mut().collect();
1251        let mut should_vec_p: Vec<i32> = (0..64).collect();
1252        let should_vec: Vec<&mut i32> = should_vec_p.iter_mut().collect();
1253        assert_eq!(should_vec, out_vec);
1254    }
1255
1256    #[test]
1257    fn consuming_iter() {
1258        let mut chunk = Chunk::<_, 64>::new();
1259        for i in 0..64 {
1260            chunk.push_back(i);
1261        }
1262        let out_vec: Vec<i32> = chunk.into_iter().collect();
1263        let should_vec: Vec<i32> = (0..64).collect();
1264        assert_eq!(should_vec, out_vec);
1265    }
1266
1267    #[test]
1268    fn insert_middle() {
1269        let mut chunk = Chunk::<_, 64>::new();
1270        for i in 0..32 {
1271            chunk.push_back(i);
1272        }
1273        for i in 33..64 {
1274            chunk.push_back(i);
1275        }
1276        chunk.insert(32, 32);
1277        let out_vec: Vec<i32> = chunk.into_iter().collect();
1278        let should_vec: Vec<i32> = (0..64).collect();
1279        assert_eq!(should_vec, out_vec);
1280    }
1281
1282    #[test]
1283    fn insert_back() {
1284        let mut chunk = Chunk::<_, 64>::new();
1285        for i in 0..63 {
1286            chunk.push_back(i);
1287        }
1288        chunk.insert(63, 63);
1289        let out_vec: Vec<i32> = chunk.into_iter().collect();
1290        let should_vec: Vec<i32> = (0..64).collect();
1291        assert_eq!(should_vec, out_vec);
1292    }
1293
1294    #[test]
1295    fn insert_front() {
1296        let mut chunk = Chunk::<_, 64>::new();
1297        for i in 1..64 {
1298            chunk.push_front(64 - i);
1299        }
1300        chunk.insert(0, 0);
1301        let out_vec: Vec<i32> = chunk.into_iter().collect();
1302        let should_vec: Vec<i32> = (0..64).collect();
1303        assert_eq!(should_vec, out_vec);
1304    }
1305
1306    #[test]
1307    fn remove_value() {
1308        let mut chunk = Chunk::<_, 64>::new();
1309        for i in 0..64 {
1310            chunk.push_back(i);
1311        }
1312        chunk.remove(32);
1313        let out_vec: Vec<i32> = chunk.into_iter().collect();
1314        let should_vec: Vec<i32> = (0..32).chain(33..64).collect();
1315        assert_eq!(should_vec, out_vec);
1316    }
1317
1318    use crate::tests::DropTest;
1319    use std::sync::atomic::{AtomicUsize, Ordering};
1320
1321    #[test]
1322    fn dropping() {
1323        let counter = AtomicUsize::new(0);
1324        {
1325            let mut chunk: Chunk<DropTest<'_>, 64> = Chunk::new();
1326            for _i in 0..20 {
1327                chunk.push_back(DropTest::new(&counter))
1328            }
1329            for _i in 0..20 {
1330                chunk.push_front(DropTest::new(&counter))
1331            }
1332            assert_eq!(40, counter.load(Ordering::Relaxed));
1333            for _i in 0..10 {
1334                chunk.pop_back();
1335            }
1336            assert_eq!(30, counter.load(Ordering::Relaxed));
1337        }
1338        assert_eq!(0, counter.load(Ordering::Relaxed));
1339    }
1340
1341    #[test]
1342    #[should_panic(expected = "assertion failed: Self::CAPACITY >= 1")]
1343    fn unit_on_empty() {
1344        Chunk::<usize, 0>::unit(1);
1345    }
1346
1347    #[test]
1348    #[should_panic(expected = "assertion failed: Self::CAPACITY >= 2")]
1349    fn pair_on_empty() {
1350        Chunk::<usize, 0>::pair(1, 2);
1351    }
1352}