Skip to content

Commit f0844b8

Browse files
committed
feat: more docs, more comments
1 parent 8e6fcfd commit f0844b8

File tree

1 file changed

+62
-33
lines changed

1 file changed

+62
-33
lines changed

src/array_impl.rs

+62-33
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@ pub struct Arrays<I: Iterator, const N: usize>
99
}
1010

1111
impl<I: Iterator, const N: usize> Arrays<I, N> {
12+
/// Creates a new Arrays iterator.
13+
/// See [`.arrays()`](crate::Itertools::arrays) for more information.
1214
pub fn new(iter: I) -> Self {
1315
Self { iter, buf: ArrayVec::new() }
1416
}
1517
}
1618
impl<I: Iterator, const N: usize> Arrays<I, N> where I::Item: Clone {
17-
pub fn remaining(self) -> Vec<I::Item> {
18-
self.buf.into_vec()
19+
/// Returns any remaining data left in the iterator.
20+
/// This is useful if the iterator has left over values
21+
/// that didn't fit into the array size.
22+
pub fn remaining(&self) -> &[I::Item] {
23+
self.buf.into_slice()
1924
}
2025
}
2126

@@ -36,19 +41,23 @@ impl<I: Iterator, const N: usize> Iterator for Arrays<I, N> {
3641
}
3742
}
3843

44+
/// Reads N elements from the iter, returning them in an array. If there's not enough
45+
/// elements, returns None.
3946
pub fn next_array<I: Iterator, const N: usize>(iter: &mut I) -> Option<[I::Item; N]> {
4047
let mut array_vec = ArrayVec::new();
4148

42-
// SAFETY:
43-
// ArrayVec::push_unchecked is safe as long as len < N.
44-
// This is guaranteed by the for loop
4549
unsafe {
50+
// SAFETY:
51+
// ArrayVec::push_unchecked is safe as long as len < N.
52+
// This is guaranteed by the for loop
4653
for _ in 0..N {
4754
array_vec.push_unchecked(iter.next()?)
4855
}
49-
}
5056

51-
array_vec.into_array()
57+
// SAFETY:
58+
// We have guaranteed to have filled all N elements
59+
Some(array_vec.into_array_unchecked())
60+
}
5261
}
5362

5463
// ArrayVec is a safe wrapper around a [T; N].
@@ -70,23 +79,44 @@ impl<T, const N: usize> Drop for ArrayVec<T, N> {
7079
}
7180

7281
impl<T, const N: usize> ArrayVec<T, N> {
82+
/// Creates a new empty ArrayVec
7383
pub const fn new() -> Self {
7484
Self {
7585
data: std::mem::MaybeUninit::uninit(),
7686
len: 0,
7787
}
7888
}
7989

90+
/// Returns the number of initialised elements in the ArrayVec
91+
pub fn len(&self) -> usize {
92+
self.len
93+
}
94+
95+
/// Returns whether the ArrayVec is empty
96+
pub fn is_empty(&self) -> bool {
97+
self.len == 0
98+
}
99+
100+
/// Returns whether the ArrayVec is full
101+
pub fn is_full(&self) -> bool {
102+
self.len == N
103+
}
104+
105+
/// Push a value into the ArrayVec
106+
///
107+
/// Panics:
108+
/// If the ArrayVec is full, this function will panic
80109
pub fn push(&mut self, v: T) {
81-
assert!(self.len < N);
82-
// SAFETY: asserts that len < N.
110+
assert!(!self.is_full());
111+
// SAFETY: asserted that self is not full
83112
unsafe { self.push_unchecked(v) }
84113
}
85114

86-
// Unsafety:
87-
// len must be less than N. If `len < N` is guaranteed, this operation is safe
88-
// This is because the contract of ArrayVec guarantees that if len < N, then the value
89-
// at len is valid and uninitialised.
115+
/// Push a value into the ArrayVec
116+
///
117+
/// Unsafety:
118+
/// The ArrayVec must not be full. If the ArrayVec is full, this function will try write data
119+
/// out-of-bounds.
90120
pub unsafe fn push_unchecked(&mut self, v: T) {
91121
// The contract of ArrayVec guarantees that the value at self.len, if < N,
92122
// is uninitialised, and therefore does not need dropping. So use write to
@@ -96,12 +126,9 @@ impl<T, const N: usize> ArrayVec<T, N> {
96126
self.len += 1;
97127
}
98128

99-
pub fn len(&self) -> usize {
100-
self.len
101-
}
102-
129+
/// If the ArrayVec is full, returns the data owned. Otherwise, returns None
103130
pub fn into_array(self) -> Option<[T; N]> {
104-
if self.len == N {
131+
if self.is_full() {
105132
// SAFETY:
106133
// If len == N, then all the data is initialised and this is safe
107134
unsafe { Some(self.into_array_unchecked()) }
@@ -110,35 +137,37 @@ impl<T, const N: usize> ArrayVec<T, N> {
110137
}
111138
}
112139

113-
// Unsafety:
114-
// len must be equal to N. If `len == N` is guaranteed, this operation is safe.
115-
// This is because the contract of ArrayVec guarantees that if len == N, all the values
116-
// have been initialised correctly.
140+
/// Returns the data owned by the ArrayVec
141+
///
142+
/// Unsafety:
143+
/// The ArrayVec must be full. If it is not full, some of the values in the array will be
144+
/// unintialised. This will cause undefined behaviour
117145
unsafe fn into_array_unchecked(mut self) -> [T; N] {
118146
// move out without dropping
119147
let data = std::mem::replace(&mut self.data, std::mem::MaybeUninit::uninit().assume_init());
120148
std::mem::forget(self);
121149
data.assume_init()
122150
}
123151

124-
// Unsafety:
125-
// len must be equal to N. If `len == N` is guaranteed, this operation is safe.
126-
// This is because the contract of ArrayVec guarantees that if len == N, all the values
127-
// have been initialised correctly.
152+
/// Returns the data owned by the ArrayVec, resetting the ArrayVec to an empty state
153+
///
154+
/// Unsafety:
155+
/// len must be equal to N. If `len == N` is guaranteed, this operation is safe.
156+
/// This is because the contract of ArrayVec guarantees that if len == N, all the values
157+
/// have been initialised correctly.
128158
unsafe fn take_unchecked(&mut self) -> [T; N] {
129159
let data = std::mem::replace(&mut self.data, std::mem::MaybeUninit::uninit().assume_init());
130160
self.len = 0;
131161
data.assume_init()
132162
}
133-
}
134163

135-
impl<T: Clone, const N: usize> ArrayVec<T, N> {
136-
pub fn into_vec(mut self) -> Vec<T> {
164+
/// Borrows the initialised data in the ArrayVec
165+
pub fn into_slice(&self) -> &[T] {
137166
unsafe {
138-
let data = std::mem::replace(&mut self.data, std::mem::MaybeUninit::uninit().assume_init());
139-
let len = self.len;
140-
std::mem::forget(self);
141-
std::slice::from_raw_parts(data.as_ptr() as *const T, len).to_vec()
167+
// let data = std::mem::replace(&mut self.data, std::mem::MaybeUninit::uninit().assume_init());
168+
// let len = self.len;
169+
// std::mem::forget(self);
170+
std::slice::from_raw_parts(self.data.as_ptr() as *const T, self.len)
142171
}
143172
}
144173
}

0 commit comments

Comments
 (0)