[−][src]Struct sized_chunks::Chunk
A fixed capacity smart array.
An inline array of items with a variable length but a fixed, preallocated
capacity given by the N
type, which must be an Unsigned
type
level numeral.
It's 'smart' because it's able to reorganise its contents based on expected
behaviour. If you construct one using push_back
, it will be laid out like
a Vec
with space at the end. If you push_front
it will start filling in
values from the back instead of the front, so that you still get linear time
push as long as you don't reverse direction. If you do, and there's no room
at the end you're pushing to, it'll shift its contents over to the other
side, creating more space to push into. This technique is tuned for
Chunk
's expected use case in im::Vector: usually, chunks always see
either push_front
or push_back
, but not both unless they move around
inside the tree, in which case they're able to reorganise themselves with
reasonable efficiency to suit their new usage patterns.
It maintains a left
index and a right
index instead of a simple length
counter in order to accomplish this, much like a ring buffer would, except
that the Chunk
keeps all its items sequentially in memory so that you can
always get a &[A]
slice for them, at the price of the occasional
reordering operation. The allocated size of a Chunk
is thus usize
* 2 +
A
* N
.
This technique also lets us choose to shift the shortest side to account for
the inserted or removed element when performing insert and remove
operations, unlike Vec
where you always need to shift the right hand side.
Unlike a Vec
, the Chunk
has a fixed capacity and cannot grow beyond it.
Being intended for low level use, it expects you to know or test whether
you're pushing to a full array, and has an API more geared towards panics
than returning Option
s, on the assumption that you know what you're doing.
Of course, if you don't, you can expect it to panic immediately rather than
do something undefined and usually bad.
Isn't this just a less efficient ring buffer?
You might be wondering why you would want to use this data structure rather
than a ring buffer, which is similar but doesn't need to shift its content
around when it hits the sides of the allocated buffer. The answer is that
Chunk
can be dereferenced into a slice, while a ring buffer can not. If
you don't need to be able to do that, a ring buffer will generally be the
more efficient choice.
Examples
// Construct a chunk with a 64 item capacity let mut chunk = Chunk::<i32, U64>::new(); // Fill it with descending numbers chunk.extend((0..64).rev()); // It derefs to a slice so we can use standard slice methods chunk.sort(); // It's got all the amenities like `FromIterator` and `Eq` let expected: Chunk<i32, U64> = (0..64).collect(); assert_eq!(expected, chunk);
Methods
impl<A, N> Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
pub fn new() -> Self
[src]
Construct a new empty chunk.
pub fn unit(value: A) -> Self
[src]
Construct a new chunk with one item.
pub fn pair(left: A, right: A) -> Self
[src]
Construct a new chunk with two items.
pub fn drain_from(other: &mut Self) -> Self
[src]
Construct a new chunk and move every item from other
into the new
chunk.
Time: O(n)
pub fn collect_from<I>(iter: &mut I, count: usize) -> Self where
I: Iterator<Item = A>,
[src]
I: Iterator<Item = A>,
Construct a new chunk and populate it by taking count
items from the
iterator iter
.
Panics if the iterator contains less than count
items.
Time: O(n)
pub fn from_front(other: &mut Self, count: usize) -> Self
[src]
Construct a new chunk and populate it by taking count
items from the
front of other
.
Time: O(n) for the number of items moved
pub fn from_back(other: &mut Self, count: usize) -> Self
[src]
Construct a new chunk and populate it by taking count
items from the
back of other
.
Time: O(n) for the number of items moved
pub fn len(&self) -> usize
[src]
Get the length of the chunk.
pub fn capacity() -> usize
[src]
Get the capacity of a chunk of this type.
pub fn is_empty(&self) -> bool
[src]
Test if the chunk is empty.
pub fn is_full(&self) -> bool
[src]
Test if the chunk is at capacity.
pub fn push_front(&mut self, value: A)
[src]
Push an item to the front of the chunk.
Panics if the capacity of the chunk is exceeded.
Time: O(1) if there's room at the front, O(n) otherwise
pub fn push_back(&mut self, value: A)
[src]
Push an item to the back of the chunk.
Panics if the capacity of the chunk is exceeded.
Time: O(1) if there's room at the back, O(n) otherwise
pub fn pop_front(&mut self) -> A
[src]
Pop an item off the front of the chunk.
Panics if the chunk is empty.
Time: O(1)
pub fn pop_back(&mut self) -> A
[src]
Pop an item off the back of the chunk.
Panics if the chunk is empty.
Time: O(1)
pub fn drop_left(&mut self, index: usize)
[src]
Discard all items up to but not including index
.
Panics if index
is out of bounds.
Time: O(n) for the number of items dropped
pub fn drop_right(&mut self, index: usize)
[src]
Discard all items from index
onward.
Panics if index
is out of bounds.
Time: O(n) for the number of items dropped
pub fn split_off(&mut self, index: usize) -> Self
[src]
Split a chunk into two, the original chunk containing
everything up to index
and the returned chunk containing
everything from index
onwards.
Panics if index
is out of bounds.
Time: O(n) for the number of items in the new chunk
pub fn append(&mut self, other: &mut Self)
[src]
Remove all items from other
and append them to the back of self
.
Panics if the capacity of the chunk is exceeded.
Time: O(n) for the number of items moved
pub fn drain_from_front(&mut self, other: &mut Self, count: usize)
[src]
Remove count
items from the front of other
and append them to the
back of self
.
Panics if self
doesn't have count
items left, or if other
has
fewer than count
items.
Time: O(n) for the number of items moved
pub fn drain_from_back(&mut self, other: &mut Self, count: usize)
[src]
Remove count
items from the back of other
and append them to the
front of self
.
Panics if self
doesn't have count
items left, or if other
has
fewer than count
items.
Time: O(n) for the number of items moved
pub fn set(&mut self, index: usize, value: A) -> A
[src]
Update the value at index index
, returning the old value.
Panics if index
is out of bounds.
Time: O(1)
pub fn insert(&mut self, index: usize, value: A)
[src]
Insert a new value at index index
, shifting all the following values
to the right.
Panics if the index is out of bounds.
Time: O(n) for the number of items shifted
pub fn remove(&mut self, index: usize) -> A
[src]
Remove the value at index index
, shifting all the following values to
the left.
Returns the removed value.
Panics if the index is out of bounds.
Time: O(n) for the number of items shifted
ⓘImportant traits for Drain<'a, A, N>pub fn drain(&mut self) -> Drain<A, N>
[src]
Construct an iterator that drains values from the front of the chunk.
pub fn clear(&mut self)
[src]
Discard the contents of the chunk.
Time: O(n)
pub fn as_slice(&self) -> &[A]
[src]
Get a reference to the contents of the chunk as a slice.
pub fn as_mut_slice(&mut self) -> &mut [A]
[src]
Get a reference to the contents of the chunk as a mutable slice.
Trait Implementations
impl<A, N> Clone for Chunk<A, N> where
A: Clone,
N: ChunkLength<A>,
[src]
A: Clone,
N: ChunkLength<A>,
fn clone(&self) -> Self
[src]
default fn clone_from(&mut self, source: &Self)
1.0.0[src]
Performs copy-assignment from source
. Read more
impl<'a, A, N> IntoIterator for &'a Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
type Item = &'a A
The type of the elements being iterated over.
type IntoIter = SliceIter<'a, A>
Which kind of iterator are we turning this into?
fn into_iter(self) -> Self::IntoIter
[src]
impl<'a, A, N> IntoIterator for &'a mut Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
type Item = &'a mut A
The type of the elements being iterated over.
type IntoIter = SliceIterMut<'a, A>
Which kind of iterator are we turning this into?
fn into_iter(self) -> Self::IntoIter
[src]
impl<A, N> IntoIterator for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
type Item = A
The type of the elements being iterated over.
type IntoIter = Iter<A, N>
Which kind of iterator are we turning this into?
fn into_iter(self) -> Self::IntoIter
[src]
impl<A, N> Eq for Chunk<A, N> where
A: Eq,
N: ChunkLength<A>,
[src]
A: Eq,
N: ChunkLength<A>,
impl<A, N> Extend<A> for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
fn extend<I>(&mut self, it: I) where
I: IntoIterator<Item = A>,
[src]
I: IntoIterator<Item = A>,
Append the contents of the iterator to the back of the chunk.
Panics if the chunk exceeds its capacity.
Time: O(n) for the length of the iterator
impl<'a, A, N> Extend<&'a A> for Chunk<A, N> where
A: 'a + Copy,
N: ChunkLength<A>,
[src]
A: 'a + Copy,
N: ChunkLength<A>,
fn extend<I>(&mut self, it: I) where
I: IntoIterator<Item = &'a A>,
[src]
I: IntoIterator<Item = &'a A>,
Append the contents of the iterator to the back of the chunk.
Panics if the chunk exceeds its capacity.
Time: O(n) for the length of the iterator
impl<A, N> Drop for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
impl<A, N> PartialOrd<Chunk<A, N>> for Chunk<A, N> where
A: PartialOrd,
N: ChunkLength<A>,
[src]
A: PartialOrd,
N: ChunkLength<A>,
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
[src]
#[must_use]
default fn lt(&self, other: &Rhs) -> bool
1.0.0[src]
This method tests less than (for self
and other
) and is used by the <
operator. Read more
#[must_use]
default fn le(&self, other: &Rhs) -> bool
1.0.0[src]
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
#[must_use]
default fn gt(&self, other: &Rhs) -> bool
1.0.0[src]
This method tests greater than (for self
and other
) and is used by the >
operator. Read more
#[must_use]
default fn ge(&self, other: &Rhs) -> bool
1.0.0[src]
This method tests greater than or equal to (for self
and other
) and is used by the >=
operator. Read more
impl<A, N> AsMut<[A]> for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
impl<A, N, Slice> PartialEq<Slice> for Chunk<A, N> where
Slice: Borrow<[A]>,
A: PartialEq,
N: ChunkLength<A>,
[src]
Slice: Borrow<[A]>,
A: PartialEq,
N: ChunkLength<A>,
fn eq(&self, other: &Slice) -> bool
[src]
#[must_use]
default fn ne(&self, other: &Rhs) -> bool
1.0.0[src]
This method tests for !=
.
impl<A, N> AsRef<[A]> for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
impl<A, N> Default for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
impl<A, N> Ord for Chunk<A, N> where
A: Ord,
N: ChunkLength<A>,
[src]
A: Ord,
N: ChunkLength<A>,
fn cmp(&self, other: &Self) -> Ordering
[src]
default fn max(self, other: Self) -> Self
1.21.0[src]
Compares and returns the maximum of two values. Read more
default fn min(self, other: Self) -> Self
1.21.0[src]
Compares and returns the minimum of two values. Read more
default fn clamp(self, min: Self, max: Self) -> Self
[src]
clamp
)Restrict a value to a certain interval. Read more
impl<A, N> Debug for Chunk<A, N> where
A: Debug,
N: ChunkLength<A>,
[src]
A: Debug,
N: ChunkLength<A>,
impl<A, N, I> Index<I> for Chunk<A, N> where
I: SliceIndex<[A]>,
N: ChunkLength<A>,
[src]
I: SliceIndex<[A]>,
N: ChunkLength<A>,
type Output = I::Output
The returned type after indexing.
fn index(&self, index: I) -> &Self::Output
[src]
impl<A, N> DerefMut for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
impl<A, N> Deref for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
impl<A, N, I> IndexMut<I> for Chunk<A, N> where
I: SliceIndex<[A]>,
N: ChunkLength<A>,
[src]
I: SliceIndex<[A]>,
N: ChunkLength<A>,
impl<A, N> Hash for Chunk<A, N> where
A: Hash,
N: ChunkLength<A>,
[src]
A: Hash,
N: ChunkLength<A>,
fn hash<H>(&self, hasher: &mut H) where
H: Hasher,
[src]
H: Hasher,
default fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
1.3.0[src]
H: Hasher,
Feeds a slice of this type into the given [Hasher
]. Read more
impl<A, N> FromIterator<A> for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
fn from_iter<I>(it: I) -> Self where
I: IntoIterator<Item = A>,
[src]
I: IntoIterator<Item = A>,
impl<A, N> Borrow<[A]> for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
impl<N> Write for Chunk<u8, N> where
N: ChunkLength<u8>,
[src]
N: ChunkLength<u8>,
fn write(&mut self, buf: &[u8]) -> Result<usize>
[src]
fn flush(&mut self) -> Result<()>
[src]
default fn write_vectored(&mut self, bufs: &[IoVec]) -> Result<usize, Error>
[src]
iovec
)Like write
, except that it writes from a slice of buffers. Read more
default fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
1.0.0[src]
Attempts to write an entire buffer into this writer. Read more
default fn write_fmt(&mut self, fmt: Arguments) -> Result<(), Error>
1.0.0[src]
Writes a formatted string into this writer, returning any error encountered. Read more
default fn by_ref(&mut self) -> &mut Self
1.0.0[src]
Creates a "by reference" adaptor for this instance of Write
. Read more
impl<A, N> BorrowMut<[A]> for Chunk<A, N> where
N: ChunkLength<A>,
[src]
N: ChunkLength<A>,
fn borrow_mut(&mut self) -> &mut [A]
[src]
Auto Trait Implementations
impl<A, N> Send for Chunk<A, N> where
<N as ChunkLength<A>>::SizedType: Send,
<N as ChunkLength<A>>::SizedType: Send,
impl<A, N> Sync for Chunk<A, N> where
<N as ChunkLength<A>>::SizedType: Sync,
<N as ChunkLength<A>>::SizedType: Sync,
Blanket Implementations
impl<I> IntoIterator for I where
I: Iterator,
[src]
I: Iterator,
type Item = <I as Iterator>::Item
The type of the elements being iterated over.
type IntoIter = I
Which kind of iterator are we turning this into?
fn into_iter(self) -> I
[src]
impl<T, U> Into for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
impl<T> From for T
[src]
impl<T, U> TryFrom for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T> Borrow for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T, U> TryInto for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Same for T
[src]
type Output = T
Should always be Self