Skip to content

Commit 481afb4

Browse files
committed
Create and use a decent private API for Array Builder/Consumer
1 parent 38954dc commit 481afb4

File tree

2 files changed

+138
-101
lines changed

2 files changed

+138
-101
lines changed

src/lib.rs

Lines changed: 125 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -161,22 +161,41 @@ where
161161
}
162162
}
163163

164+
/// Creates an array one element at a time using a mutable iterator
165+
/// you can write to with `ptr::write`.
166+
///
167+
/// Incremenent the position while iterating to mark off created elements,
168+
/// which will be dropped if `into_inner` is not called.
164169
#[doc(hidden)]
165170
pub struct ArrayBuilder<T, N: ArrayLength<T>> {
166-
pub array: ManuallyDrop<GenericArray<T, N>>,
167-
pub position: usize,
171+
array: ManuallyDrop<GenericArray<T, N>>,
172+
position: usize,
168173
}
169174

170175
impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
171176
#[doc(hidden)]
177+
#[inline]
172178
pub unsafe fn new() -> ArrayBuilder<T, N> {
173179
ArrayBuilder {
174180
array: ManuallyDrop::new(mem::uninitialized()),
175181
position: 0,
176182
}
177183
}
178184

185+
/// Creates a mutable iterator for writing to the array using `ptr::write`.
186+
///
187+
/// Increment the position value given as a mutable reference as you iterate
188+
/// to mark how many elements have been created.
189+
#[doc(hidden)]
190+
#[inline]
191+
pub unsafe fn iter_position(&mut self) -> (slice::IterMut<T>, &mut usize) {
192+
(self.array.iter_mut(), &mut self.position)
193+
}
194+
195+
/// When done writing (assuming all elements have been written to),
196+
/// get the inner array.
179197
#[doc(hidden)]
198+
#[inline]
180199
pub unsafe fn into_inner(self) -> GenericArray<T, N> {
181200
let array = ptr::read(&self.array);
182201

@@ -188,35 +207,50 @@ impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
188207

189208
impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {
190209
fn drop(&mut self) {
191-
for value in self.array.iter_mut().take(self.position) {
210+
for value in &mut self.array[..self.position] {
192211
unsafe {
193212
ptr::drop_in_place(value);
194213
}
195214
}
196215
}
197216
}
198217

218+
/// Consumes an array.
219+
///
220+
/// Increment the position while iterating and any leftover elements
221+
/// will be dropped if position does not go to N
199222
#[doc(hidden)]
200223
pub struct ArrayConsumer<T, N: ArrayLength<T>> {
201-
pub array: ManuallyDrop<GenericArray<T, N>>,
202-
pub position: usize,
224+
array: ManuallyDrop<GenericArray<T, N>>,
225+
position: usize,
203226
}
204227

205228
impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {
206229
#[doc(hidden)]
230+
#[inline]
207231
pub unsafe fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
208232
ArrayConsumer {
209233
array: ManuallyDrop::new(array),
210234
position: 0,
211235
}
212236
}
237+
238+
/// Creates an iterator and mutable reference to the internal position
239+
/// to keep track of consumed elements.
240+
///
241+
/// Increment the position as you iterate to mark off consumed elements
242+
#[doc(hidden)]
243+
#[inline]
244+
pub unsafe fn iter_position(&mut self) -> (slice::Iter<T>, &mut usize) {
245+
(self.array.iter(), &mut self.position)
246+
}
213247
}
214248

215249
impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {
216250
fn drop(&mut self) {
217-
for i in self.position..N::to_usize() {
251+
for value in &mut self.array[self.position..N::to_usize()] {
218252
unsafe {
219-
ptr::drop_in_place(self.array.get_unchecked_mut(i));
253+
ptr::drop_in_place(value);
220254
}
221255
}
222256
}
@@ -254,21 +288,25 @@ where
254288
where
255289
I: IntoIterator<Item = T>,
256290
{
257-
let mut destination = unsafe { ArrayBuilder::new() };
291+
unsafe {
292+
let mut destination = ArrayBuilder::new();
258293

259-
for (src, dst) in iter.into_iter().zip(destination.array.iter_mut()) {
260-
unsafe {
261-
ptr::write(dst, src);
294+
{
295+
let (destination_iter, position) = destination.iter_position();
296+
297+
for (src, dst) in iter.into_iter().zip(destination_iter) {
298+
ptr::write(dst, src);
299+
300+
*position += 1;
301+
}
262302
}
263303

264-
destination.position += 1;
265-
}
304+
if destination.position < N::to_usize() {
305+
from_iter_length_fail(destination.position, N::to_usize());
306+
}
266307

267-
if destination.position < N::to_usize() {
268-
from_iter_length_fail(destination.position, N::to_usize());
308+
destination.into_inner()
269309
}
270-
271-
unsafe { destination.into_inner() }
272310
}
273311
}
274312

@@ -293,17 +331,21 @@ where
293331
where
294332
F: FnMut(usize) -> T,
295333
{
296-
let mut destination = unsafe { ArrayBuilder::new() };
334+
unsafe {
335+
let mut destination = ArrayBuilder::new();
297336

298-
for (i, dst) in destination.array.iter_mut().enumerate() {
299-
unsafe {
300-
ptr::write(dst, f(i));
337+
{
338+
let (destination_iter, position) = destination.iter_position();
339+
340+
for (i, dst) in destination_iter.enumerate() {
341+
ptr::write(dst, f(i));
342+
343+
*position += 1;
344+
}
301345
}
302346

303-
destination.position += 1;
347+
destination.into_inner()
304348
}
305-
306-
unsafe { destination.into_inner() }
307349
}
308350

309351
#[doc(hidden)]
@@ -319,27 +361,23 @@ where
319361
Self::Length: ArrayLength<B> + ArrayLength<U>,
320362
F: FnMut(B, Self::Item) -> U,
321363
{
322-
let mut left = unsafe { ArrayConsumer::new(lhs) };
323-
let mut right = unsafe { ArrayConsumer::new(self) };
324-
325-
let ArrayConsumer {
326-
array: ref left_array,
327-
position: ref mut left_position,
328-
} = left;
329-
let ArrayConsumer {
330-
array: ref right_array,
331-
position: ref mut right_position,
332-
} = right;
333-
334-
FromIterator::from_iter(left_array.iter().zip(right_array.iter()).map(|(l, r)| {
335-
let left_value = unsafe { ptr::read(l) };
336-
let right_value = unsafe { ptr::read(r) };
337-
338-
*left_position += 1;
339-
*right_position += 1;
340-
341-
f(left_value, right_value)
342-
}))
364+
unsafe {
365+
let mut left = ArrayConsumer::new(lhs);
366+
let mut right = ArrayConsumer::new(self);
367+
368+
let (left_array_iter, left_position) = left.iter_position();
369+
let (right_array_iter, right_position) = right.iter_position();
370+
371+
FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {
372+
let left_value = ptr::read(l);
373+
let right_value = ptr::read(r);
374+
375+
*left_position += 1;
376+
*right_position += 1;
377+
378+
f(left_value, right_value)
379+
}))
380+
}
343381
}
344382

345383
#[doc(hidden)]
@@ -350,24 +388,23 @@ where
350388
Self::Length: ArrayLength<B> + ArrayLength<U>,
351389
F: FnMut(Lhs::Item, Self::Item) -> U,
352390
{
353-
let mut right = unsafe { ArrayConsumer::new(self) };
391+
unsafe {
392+
let mut right = ArrayConsumer::new(self);
354393

355-
let ArrayConsumer {
356-
array: ref right_array,
357-
position: ref mut right_position,
358-
} = right;
394+
let (right_array_iter, right_position) = right.iter_position();
359395

360-
FromIterator::from_iter(
361-
lhs.into_iter()
362-
.zip(right_array.iter())
363-
.map(|(left_value, r)| {
364-
let right_value = unsafe { ptr::read(r) };
396+
FromIterator::from_iter(
397+
lhs.into_iter()
398+
.zip(right_array_iter)
399+
.map(|(left_value, r)| {
400+
let right_value = ptr::read(r);
365401

366-
*right_position += 1;
402+
*right_position += 1;
367403

368-
f(left_value, right_value)
369-
}),
370-
)
404+
f(left_value, right_value)
405+
}),
406+
)
407+
}
371408
}
372409
}
373410

@@ -390,20 +427,19 @@ where
390427
Self: MappedGenericSequence<T, U>,
391428
F: FnMut(T) -> U,
392429
{
393-
let mut source = unsafe { ArrayConsumer::new(self) };
430+
unsafe {
431+
let mut source = ArrayConsumer::new(self);
394432

395-
let ArrayConsumer {
396-
ref array,
397-
ref mut position,
398-
} = source;
433+
let (array_iter, position) = source.iter_position();
399434

400-
FromIterator::from_iter(array.iter().map(|src| {
401-
let value = unsafe { ptr::read(src) };
435+
FromIterator::from_iter(array_iter.map(|src| {
436+
let value = ptr::read(src);
402437

403-
*position += 1;
438+
*position += 1;
404439

405-
f(value)
406-
}))
440+
f(value)
441+
}))
442+
}
407443
}
408444

409445
#[inline]
@@ -422,20 +458,19 @@ where
422458
where
423459
F: FnMut(U, T) -> U,
424460
{
425-
let mut source = unsafe { ArrayConsumer::new(self) };
461+
unsafe {
462+
let mut source = ArrayConsumer::new(self);
426463

427-
let ArrayConsumer {
428-
ref array,
429-
ref mut position,
430-
} = source;
464+
let (array_iter, position) = source.iter_position();
431465

432-
array.iter().fold(init, |acc, src| {
433-
let value = unsafe { ptr::read(src) };
466+
array_iter.fold(init, |acc, src| {
467+
let value = ptr::read(src);
434468

435-
*position += 1;
469+
*position += 1;
436470

437-
f(acc, value)
438-
})
471+
f(acc, value)
472+
})
473+
}
439474
}
440475
}
441476

@@ -525,17 +560,21 @@ where
525560
let iter = iter.into_iter();
526561

527562
if iter.len() == N::to_usize() {
528-
let mut destination = unsafe { ArrayBuilder::new() };
563+
unsafe {
564+
let mut destination = ArrayBuilder::new();
529565

530-
for (dst, src) in destination.array.iter_mut().zip(iter.into_iter()) {
531-
unsafe {
532-
ptr::write(dst, src);
566+
{
567+
let (destination_iter, position) = destination.iter_position();
568+
569+
for (dst, src) in destination_iter.zip(iter.into_iter()) {
570+
ptr::write(dst, src);
571+
572+
*position += 1;
573+
}
533574
}
534575

535-
destination.position += 1;
576+
Some(destination.into_inner())
536577
}
537-
538-
Some(unsafe { destination.into_inner() })
539578
} else {
540579
None
541580
}

src/sequence.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,23 @@ pub unsafe trait GenericSequence<T>: Sized + IntoIterator {
3636
Self::Length: ArrayLength<B> + ArrayLength<U>,
3737
F: FnMut(B, Self::Item) -> U,
3838
{
39-
let mut left = unsafe { ArrayConsumer::new(lhs) };
39+
unsafe {
40+
let mut left = ArrayConsumer::new(lhs);
4041

41-
let ArrayConsumer {
42-
array: ref left_array,
43-
position: ref mut left_position,
44-
} = left;
42+
let (left_array_iter, left_position) = left.iter_position();
4543

46-
FromIterator::from_iter(
47-
left_array
48-
.iter()
49-
.zip(self.into_iter())
50-
.map(|(l, right_value)| {
51-
let left_value = unsafe { ptr::read(l) };
44+
FromIterator::from_iter(
45+
left_array_iter
46+
.zip(self.into_iter())
47+
.map(|(l, right_value)| {
48+
let left_value = ptr::read(l);
5249

53-
*left_position += 1;
50+
*left_position += 1;
5451

55-
f(left_value, right_value)
56-
}),
57-
)
52+
f(left_value, right_value)
53+
})
54+
)
55+
}
5856
}
5957

6058
#[doc(hidden)]

0 commit comments

Comments
 (0)