Skip to content

Commit c653aa3

Browse files
authored
Merge pull request #62 from novacrazy/master
Make Array Consumer/Builder structures public, but hidden, for use in other crates
2 parents 95d57f4 + 481afb4 commit c653aa3

File tree

2 files changed

+146
-104
lines changed

2 files changed

+146
-104
lines changed

src/lib.rs

Lines changed: 133 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -161,21 +161,43 @@ where
161161
}
162162
}
163163

164-
struct ArrayBuilder<T, N: ArrayLength<T>> {
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.
169+
#[doc(hidden)]
170+
pub struct ArrayBuilder<T, N: ArrayLength<T>> {
165171
array: ManuallyDrop<GenericArray<T, N>>,
166172
position: usize,
167173
}
168174

169175
impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
170-
fn new() -> ArrayBuilder<T, N> {
176+
#[doc(hidden)]
177+
#[inline]
178+
pub unsafe fn new() -> ArrayBuilder<T, N> {
171179
ArrayBuilder {
172-
array: ManuallyDrop::new(unsafe { mem::uninitialized() }),
180+
array: ManuallyDrop::new(mem::uninitialized()),
173181
position: 0,
174182
}
175183
}
176184

177-
fn into_inner(self) -> GenericArray<T, N> {
178-
let array = unsafe { ptr::read(&self.array) };
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.
197+
#[doc(hidden)]
198+
#[inline]
199+
pub unsafe fn into_inner(self) -> GenericArray<T, N> {
200+
let array = ptr::read(&self.array);
179201

180202
mem::forget(self);
181203

@@ -185,33 +207,50 @@ impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
185207

186208
impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {
187209
fn drop(&mut self) {
188-
for value in self.array.iter_mut().take(self.position) {
210+
for value in &mut self.array[..self.position] {
189211
unsafe {
190212
ptr::drop_in_place(value);
191213
}
192214
}
193215
}
194216
}
195217

196-
struct ArrayConsumer<T, N: ArrayLength<T>> {
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
222+
#[doc(hidden)]
223+
pub struct ArrayConsumer<T, N: ArrayLength<T>> {
197224
array: ManuallyDrop<GenericArray<T, N>>,
198225
position: usize,
199226
}
200227

201228
impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {
202-
fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
229+
#[doc(hidden)]
230+
#[inline]
231+
pub unsafe fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
203232
ArrayConsumer {
204233
array: ManuallyDrop::new(array),
205234
position: 0,
206235
}
207236
}
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+
}
208247
}
209248

210249
impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {
211250
fn drop(&mut self) {
212-
for i in self.position..N::to_usize() {
251+
for value in &mut self.array[self.position..N::to_usize()] {
213252
unsafe {
214-
ptr::drop_in_place(self.array.get_unchecked_mut(i));
253+
ptr::drop_in_place(value);
215254
}
216255
}
217256
}
@@ -249,21 +288,25 @@ where
249288
where
250289
I: IntoIterator<Item = T>,
251290
{
252-
let mut destination = ArrayBuilder::new();
291+
unsafe {
292+
let mut destination = ArrayBuilder::new();
253293

254-
for (src, dst) in iter.into_iter().zip(destination.array.iter_mut()) {
255-
unsafe {
256-
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+
}
257302
}
258303

259-
destination.position += 1;
260-
}
304+
if destination.position < N::to_usize() {
305+
from_iter_length_fail(destination.position, N::to_usize());
306+
}
261307

262-
if destination.position < N::to_usize() {
263-
from_iter_length_fail(destination.position, N::to_usize());
308+
destination.into_inner()
264309
}
265-
266-
destination.into_inner()
267310
}
268311
}
269312

@@ -288,17 +331,21 @@ where
288331
where
289332
F: FnMut(usize) -> T,
290333
{
291-
let mut destination = ArrayBuilder::new();
334+
unsafe {
335+
let mut destination = ArrayBuilder::new();
292336

293-
for (i, dst) in destination.array.iter_mut().enumerate() {
294-
unsafe {
295-
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+
}
296345
}
297346

298-
destination.position += 1;
347+
destination.into_inner()
299348
}
300-
301-
destination.into_inner()
302349
}
303350

304351
#[doc(hidden)]
@@ -314,27 +361,23 @@ where
314361
Self::Length: ArrayLength<B> + ArrayLength<U>,
315362
F: FnMut(B, Self::Item) -> U,
316363
{
317-
let mut left = ArrayConsumer::new(lhs);
318-
let mut right = ArrayConsumer::new(self);
319-
320-
let ArrayConsumer {
321-
array: ref left_array,
322-
position: ref mut left_position,
323-
} = left;
324-
let ArrayConsumer {
325-
array: ref right_array,
326-
position: ref mut right_position,
327-
} = right;
328-
329-
FromIterator::from_iter(left_array.iter().zip(right_array.iter()).map(|(l, r)| {
330-
let left_value = unsafe { ptr::read(l) };
331-
let right_value = unsafe { ptr::read(r) };
332-
333-
*left_position += 1;
334-
*right_position += 1;
335-
336-
f(left_value, right_value)
337-
}))
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+
}
338381
}
339382

340383
#[doc(hidden)]
@@ -345,24 +388,23 @@ where
345388
Self::Length: ArrayLength<B> + ArrayLength<U>,
346389
F: FnMut(Lhs::Item, Self::Item) -> U,
347390
{
348-
let mut right = ArrayConsumer::new(self);
391+
unsafe {
392+
let mut right = ArrayConsumer::new(self);
349393

350-
let ArrayConsumer {
351-
array: ref right_array,
352-
position: ref mut right_position,
353-
} = right;
394+
let (right_array_iter, right_position) = right.iter_position();
354395

355-
FromIterator::from_iter(
356-
lhs.into_iter()
357-
.zip(right_array.iter())
358-
.map(|(left_value, r)| {
359-
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);
360401

361-
*right_position += 1;
402+
*right_position += 1;
362403

363-
f(left_value, right_value)
364-
}),
365-
)
404+
f(left_value, right_value)
405+
}),
406+
)
407+
}
366408
}
367409
}
368410

@@ -385,20 +427,19 @@ where
385427
Self: MappedGenericSequence<T, U>,
386428
F: FnMut(T) -> U,
387429
{
388-
let mut source = ArrayConsumer::new(self);
430+
unsafe {
431+
let mut source = ArrayConsumer::new(self);
389432

390-
let ArrayConsumer {
391-
ref array,
392-
ref mut position,
393-
} = source;
433+
let (array_iter, position) = source.iter_position();
394434

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

398-
*position += 1;
438+
*position += 1;
399439

400-
f(value)
401-
}))
440+
f(value)
441+
}))
442+
}
402443
}
403444

404445
#[inline]
@@ -417,20 +458,19 @@ where
417458
where
418459
F: FnMut(U, T) -> U,
419460
{
420-
let mut source = ArrayConsumer::new(self);
461+
unsafe {
462+
let mut source = ArrayConsumer::new(self);
421463

422-
let ArrayConsumer {
423-
ref array,
424-
ref mut position,
425-
} = source;
464+
let (array_iter, position) = source.iter_position();
426465

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

430-
*position += 1;
469+
*position += 1;
431470

432-
f(acc, value)
433-
})
471+
f(acc, value)
472+
})
473+
}
434474
}
435475
}
436476

@@ -520,17 +560,21 @@ where
520560
let iter = iter.into_iter();
521561

522562
if iter.len() == N::to_usize() {
523-
let mut destination = ArrayBuilder::new();
563+
unsafe {
564+
let mut destination = ArrayBuilder::new();
524565

525-
for (dst, src) in destination.array.iter_mut().zip(iter.into_iter()) {
526-
unsafe {
527-
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+
}
528574
}
529575

530-
destination.position += 1;
576+
Some(destination.into_inner())
531577
}
532-
533-
Some(destination.into_inner())
534578
} else {
535579
None
536580
}

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 = 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)