diff --git a/src/hex.rs b/src/hex.rs index 3ef92b1b99..d83e28f4e9 100644 --- a/src/hex.rs +++ b/src/hex.rs @@ -15,12 +15,12 @@ //! ``` //! -use {ArrayLength, GenericArray}; use core::cmp::min; use core::fmt; use core::ops::Add; use core::str; use typenum::*; +use {ArrayLength, GenericArray}; static LOWER_CHARS: &'static [u8] = b"0123456789abcdef"; static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF"; @@ -39,10 +39,11 @@ where // buffer of 2x number of bytes let mut res = GenericArray::>::default(); - for (i, c) in self.iter().take(max_hex).enumerate() { + self.iter().take(max_hex).enumerate().for_each(|(i, c)| { res[i * 2] = LOWER_CHARS[(c >> 4) as usize]; res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; - } + }); + f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; } else { // For large array use chunks of up to 1024 bytes (2048 hex chars) @@ -50,10 +51,11 @@ where let mut digits_left = max_digits; for chunk in self[..max_hex].chunks(1024) { - for (i, c) in chunk.iter().enumerate() { + chunk.iter().enumerate().for_each(|(i, c)| { buf[i * 2] = LOWER_CHARS[(c >> 4) as usize]; buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; - } + }); + let n = min(chunk.len() * 2, digits_left); f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; digits_left -= n; @@ -77,10 +79,11 @@ where // buffer of 2x number of bytes let mut res = GenericArray::>::default(); - for (i, c) in self.iter().take(max_hex).enumerate() { + self.iter().take(max_hex).enumerate().for_each(|(i, c)| { res[i * 2] = UPPER_CHARS[(c >> 4) as usize]; res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; - } + }); + f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; } else { // For large array use chunks of up to 1024 bytes (2048 hex chars) @@ -88,10 +91,11 @@ where let mut digits_left = max_digits; for chunk in self[..max_hex].chunks(1024) { - for (i, c) in chunk.iter().enumerate() { + chunk.iter().enumerate().for_each(|(i, c)| { buf[i * 2] = UPPER_CHARS[(c >> 4) as usize]; buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; - } + }); + let n = min(chunk.len() * 2, digits_left); f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; digits_left -= n; diff --git a/src/impls.rs b/src/impls.rs index 58a1b1fb16..b362cdef0d 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -21,7 +21,7 @@ where N: ArrayLength, { fn clone(&self) -> GenericArray { - self.map(|x| x.clone()) + self.map(Clone::clone) } } @@ -40,11 +40,7 @@ where **self == **other } } -impl Eq for GenericArray -where - N: ArrayLength, -{ -} +impl Eq for GenericArray where N: ArrayLength {} impl PartialOrd for GenericArray where diff --git a/src/iter.rs b/src/iter.rs index a2d67fc679..954907ca32 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,8 +1,8 @@ //! `GenericArray` iterator implementation. use super::{ArrayLength, GenericArray}; -use core::{cmp, ptr, fmt, mem}; use core::mem::ManuallyDrop; +use core::{cmp, fmt, mem, ptr}; /// An iterator that moves out of a `GenericArray` pub struct GenericArrayIter> { @@ -131,6 +131,34 @@ where } } + fn fold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let ret = unsafe { + let GenericArrayIter { + ref array, + ref mut index, + index_back, + } = self; + + let remaining = &array[*index..index_back]; + + remaining.iter().fold(init, |acc, src| { + let value = ptr::read(src); + + *index += 1; + + f(acc, value) + }) + }; + + // ensure the drop happens here after iteration + drop(self); + + ret + } + #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); @@ -176,6 +204,34 @@ where None } } + + fn rfold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let ret = unsafe { + let GenericArrayIter { + ref array, + index, + ref mut index_back, + } = self; + + let remaining = &array[index..*index_back]; + + remaining.iter().rfold(init, |acc, src| { + let value = ptr::read(src); + + *index_back -= 1; + + f(acc, value) + }) + }; + + // ensure the drop happens here after iteration + drop(self); + + ret + } } impl ExactSizeIterator for GenericArrayIter @@ -187,4 +243,4 @@ where } } -// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized \ No newline at end of file +// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized diff --git a/src/lib.rs b/src/lib.rs index 966015185a..9694d9fff2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,9 +98,9 @@ impl Clone for GenericArrayImplEven { parent1: self.parent1.clone(), parent2: self.parent2.clone(), _marker: PhantomData, - } } } +} impl Copy for GenericArrayImplEven {} @@ -120,9 +120,9 @@ impl Clone for GenericArrayImplOdd { parent1: self.parent1.clone(), parent2: self.parent2.clone(), data: self.data.clone(), - } } } +} impl Copy for GenericArrayImplOdd {} @@ -298,11 +298,13 @@ where { let (destination_iter, position) = destination.iter_position(); - for (src, dst) in iter.into_iter().zip(destination_iter) { - ptr::write(dst, src); + iter.into_iter() + .zip(destination_iter) + .for_each(|(src, dst)| { + ptr::write(dst, src); - *position += 1; - } + *position += 1; + }); } if destination.position < N::to_usize() { @@ -341,11 +343,11 @@ where { let (destination_iter, position) = destination.iter_position(); - for (i, dst) in destination_iter.enumerate() { + destination_iter.enumerate().for_each(|(i, dst)| { ptr::write(dst, f(i)); *position += 1; - } + }); } destination.into_inner() @@ -570,11 +572,11 @@ where { let (destination_iter, position) = destination.iter_position(); - for (dst, src) in destination_iter.zip(iter.into_iter()) { + destination_iter.zip(iter).for_each(|(dst, src)| { ptr::write(dst, src); *position += 1; - } + }); } Some(destination.into_inner()) diff --git a/src/sequence.rs b/src/sequence.rs index 7b928abdae..f085a0b383 100644 --- a/src/sequence.rs +++ b/src/sequence.rs @@ -1,8 +1,8 @@ //! Useful traits for manipulating sequences of data stored in `GenericArray`s use super::*; -use core::{mem, ptr}; use core::ops::{Add, Sub}; +use core::{mem, ptr}; use typenum::operator_aliases::*; /// Defines some sequence with an associated length and iteration capabilities. @@ -41,17 +41,15 @@ pub unsafe trait GenericSequence: Sized + IntoIterator { let (left_array_iter, left_position) = left.iter_position(); - FromIterator::from_iter( - left_array_iter - .zip(self.into_iter()) - .map(|(l, right_value)| { + FromIterator::from_iter(left_array_iter.zip(self.into_iter()).map( + |(l, right_value)| { let left_value = ptr::read(l); *left_position += 1; f(left_value, right_value) - }) - ) + }, + )) } } diff --git a/tests/iter.rs b/tests/iter.rs index 47860d728b..dd2aee14fb 100644 --- a/tests/iter.rs +++ b/tests/iter.rs @@ -4,8 +4,8 @@ extern crate generic_array; use std::cell::Cell; use std::ops::Drop; -use generic_array::GenericArray; use generic_array::typenum::consts::U5; +use generic_array::GenericArray; #[test] fn test_into_iter_as_slice() { @@ -92,22 +92,37 @@ fn test_into_iter_flat_map() { assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10)); } +#[test] +fn test_into_iter_fold() { + assert_eq!( + arr![i32; 1, 2, 3, 4].into_iter().fold(0, |sum, x| sum + x), + 10 + ); + + let mut iter = arr![i32; 0, 1, 2, 3, 4, 5].into_iter(); + + iter.next(); + iter.next_back(); + + assert_eq!(iter.clone().fold(0, |sum, x| sum + x), 10); + + assert_eq!(iter.rfold(0, |sum, x| sum + x), 10); +} + #[test] fn test_into_iter_drops() { struct R<'a> { - i: &'a Cell, + i: &'a Cell, } impl<'a> Drop for R<'a> { - fn drop(&mut self) { + fn drop(&mut self) { self.i.set(self.i.get() + 1); } } fn r(i: &Cell) -> R { - R { - i: i - } + R { i: i } } fn v(i: &Cell) -> GenericArray { @@ -161,4 +176,4 @@ fn assert_covariance() { i } } -*/ \ No newline at end of file +*/ diff --git a/tests/mod.rs b/tests/mod.rs index 6c6d9eb492..81fcaac970 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -4,10 +4,10 @@ extern crate generic_array; use core::cell::Cell; use core::ops::{Add, Drop}; -use generic_array::GenericArray; use generic_array::functional::*; use generic_array::sequence::*; use generic_array::typenum::{U1, U3, U4, U97}; +use generic_array::GenericArray; #[test] fn test() { @@ -124,8 +124,8 @@ fn test_cmp() { mod impl_serde { extern crate serde_json; - use generic_array::GenericArray; use generic_array::typenum::U6; + use generic_array::GenericArray; #[test] fn test_serde_implementation() { @@ -178,20 +178,37 @@ fn test_from_iter() { #[test] fn test_sizes() { #![allow(dead_code)] + use core::ffi::c_void; use core::mem::{size_of, size_of_val}; + #[derive(Debug, Copy, Clone)] + enum E { + V, + V2(i32), + V3 { h: bool, i: i32 }, + } + #[derive(Debug, Copy, Clone)] #[repr(C)] #[repr(packed)] struct Test { t: u16, s: u32, + mm: bool, r: u16, f: u16, + p: (), o: u32, + ff: *const extern "C" fn(*const char) -> *const c_void, + l: *const c_void, + w: bool, + q: bool, + v: E, } - assert_eq!(size_of::(), 14); + assert_eq!(size_of::(), 8); + + assert_eq!(size_of::(), 25 + size_of::() * 2); assert_eq!(size_of_val(&arr![u8; 1, 2, 3]), size_of::() * 3); assert_eq!(size_of_val(&arr![u32; 1]), size_of::() * 1);