Fri, 14 Feb 2025 23:31:24 -0500
slice_assume_init_mut deprecation workaround
src/maputil.rs | file | annotate | diff | comparison | revisions |
--- a/src/maputil.rs Mon Feb 03 19:22:16 2025 -0500 +++ b/src/maputil.rs Fri Feb 14 23:31:24 2025 -0500 @@ -2,34 +2,36 @@ Utilities for mapping over various container types. */ +use itertools::izip; #[cfg(feature = "nightly")] use std::mem::MaybeUninit; -use itertools::izip; /// Trait for a fixed-length container type. -/// +/// /// Implemented by [`Loc`][crate::loc::Loc] vectors, [`Cube`][crate::sets::Cube]s, /// and basic arrays. -pub trait FixedLength<const N : usize> { +pub trait FixedLength<const N: usize> { /// Type of elements of the container. type Elem; /// Type of iterators over the elements of the container. - type Iter : Iterator<Item = Self::Elem>; + type Iter: Iterator<Item = Self::Elem>; /// Returns an iteartor over the elements of the container. fn fl_iter(self) -> Self::Iter; } /// Trait for a mutable fixed-length container type. -pub trait FixedLengthMut<const N : usize> : FixedLength<N> { +pub trait FixedLengthMut<const N: usize>: FixedLength<N> { /// Type of iterators over references to mutable elements of the container. - type IterMut<'a> : Iterator<Item=&'a mut Self::Elem> where Self : 'a; + type IterMut<'a>: Iterator<Item = &'a mut Self::Elem> + where + Self: 'a; /// Returns an iterator over mutable references to elements of the container. fn fl_iter_mut(&mut self) -> Self::IterMut<'_>; } -impl<A, const N : usize> FixedLength<N> for [A; N] { +impl<A, const N: usize> FixedLength<N> for [A; N] { type Elem = A; type Iter = std::array::IntoIter<A, N>; #[inline] @@ -38,15 +40,18 @@ } } -impl<A, const N : usize> FixedLengthMut<N> for [A; N] { - type IterMut<'a> = std::slice::IterMut<'a, A> where A : 'a; +impl<A, const N: usize> FixedLengthMut<N> for [A; N] { + type IterMut<'a> + = std::slice::IterMut<'a, A> + where + A: 'a; #[inline] fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { self.iter_mut() } } -impl<'a, A, const N : usize> FixedLength<N> for &'a [A; N] { +impl<'a, A, const N: usize> FixedLength<N> for &'a [A; N] { type Elem = &'a A; type Iter = std::slice::Iter<'a, A>; #[inline] @@ -157,10 +162,9 @@ make_mapmany_mut!(map5_mut, map5_indexed_mut, a b c d e; A B C D E, CA CB CC CD CE); make_mapmany_mut!(map6_mut, map6_indexed_mut, a b c d e f; A B C D E F, CA CB CC CD CE CF); - /// Initialise an array of length `N` by calling `f` multiple times. #[inline] -pub fn array_init<A, F : Fn() -> A, const N : usize>(f : F) -> [A; N] { +pub fn array_init<A, F: Fn() -> A, const N: usize>(f: F) -> [A; N] { //[(); N].map(|_| f()) core::array::from_fn(|_| f()) } @@ -172,17 +176,17 @@ // core::array::from_fn(f) // } - - /// Iterator returned by [`foldmap`][FoldMappable::foldmap] applied to an iterator. -pub struct FoldMap<I : Iterator<Item=A>, A, B, J : Copy, F : Fn(J, A) -> (J, B)> { - iter : I, - f : F, - j : J, +pub struct FoldMap<I: Iterator<Item = A>, A, B, J: Copy, F: Fn(J, A) -> (J, B)> { + iter: I, + f: F, + j: J, } -impl<A, B, I : Iterator<Item=A>, J : Copy, F : Fn(J, A) -> (J, B)> Iterator for FoldMap<I, A, B, J, F> { +impl<A, B, I: Iterator<Item = A>, J: Copy, F: Fn(J, A) -> (J, B)> Iterator + for FoldMap<I, A, B, J, F> +{ type Item = B; #[inline] fn next(&mut self) -> Option<B> { @@ -195,19 +199,19 @@ } /// Iterator returned by [`indexmap`][IndexMappable::indexmap] applied to an iterator. -pub struct IndexMap<I : Iterator<Item=A>, A, B, F : Fn(usize, A) -> B> { - iter : I, - f : F, - j : usize, +pub struct IndexMap<I: Iterator<Item = A>, A, B, F: Fn(usize, A) -> B> { + iter: I, + f: F, + j: usize, } -impl<A, B, I : Iterator<Item=A>, F : Fn(usize, A) -> B> Iterator for IndexMap<I, A, B, F> { +impl<A, B, I: Iterator<Item = A>, F: Fn(usize, A) -> B> Iterator for IndexMap<I, A, B, F> { type Item = B; #[inline] fn next(&mut self) -> Option<B> { self.iter.next().map(|a| { let b = (self.f)(self.j, a); - self.j = self.j+1; + self.j = self.j + 1; b }) } @@ -216,68 +220,90 @@ /// Trait for things that can be foldmapped. /// /// `A` is the type of elements of `Self`, and `J` the accumulator type for the folding. -pub trait FoldMappable<A, J> : Sized { - type Output<B, F> where F : Fn(J, A) -> (J, B); +pub trait FoldMappable<A, J>: Sized { + type Output<B, F> + where + F: Fn(J, A) -> (J, B); /// Fold and map over `self` with `f`. `j` is the initial accumulator for folding. /// /// The output type depends on the implementation, but will generally have elements of /// type `B`. - fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F>; + fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F>; } /// Trait for things that can be indexmapped. /// /// `A` is the type of elements of `Self`. -pub trait IndexMappable<A> : Sized { - type Output<B, F> where F : Fn(usize, A) -> B; +pub trait IndexMappable<A>: Sized { + type Output<B, F> + where + F: Fn(usize, A) -> B; /// Map over element indices and elements of `self`. /// /// The output type depends on the implementation, but will generally have elements of /// type `B`. - fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> Self::Output<B, F>; + fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> Self::Output<B, F>; } -impl<'a, A, J : Copy> FoldMappable<&'a A, J> -for std::slice::Iter<'a, A> { - type Output<B, F> = FoldMap<Self, &'a A, B, J, F> where F : Fn(J, &'a A) -> (J, B); +impl<'a, A, J: Copy> FoldMappable<&'a A, J> for std::slice::Iter<'a, A> { + type Output<B, F> + = FoldMap<Self, &'a A, B, J, F> + where + F: Fn(J, &'a A) -> (J, B); #[inline] - fn foldmap<B, F : Fn(J, &'a A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F> { - FoldMap { iter : self, j, f } + fn foldmap<B, F: Fn(J, &'a A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F> { + FoldMap { iter: self, j, f } } } -impl<'a, A> IndexMappable<&'a A> -for std::slice::Iter<'a, A> { - type Output<B, F> = IndexMap<Self, &'a A, B, F> where F : Fn(usize, &'a A) -> B; +impl<'a, A> IndexMappable<&'a A> for std::slice::Iter<'a, A> { + type Output<B, F> + = IndexMap<Self, &'a A, B, F> + where + F: Fn(usize, &'a A) -> B; #[inline] - fn indexmap<B, F : Fn(usize, &'a A) -> B>(self, f : F) -> Self::Output<B, F> { - IndexMap { iter : self, j : 0, f } + fn indexmap<B, F: Fn(usize, &'a A) -> B>(self, f: F) -> Self::Output<B, F> { + IndexMap { + iter: self, + j: 0, + f, + } } } - -impl<A, J : Copy, const N : usize> FoldMappable<A, J> -for std::array::IntoIter<A, N> { - type Output<B, F> = FoldMap<Self, A, B, J, F> where F : Fn(J, A) -> (J, B); +impl<A, J: Copy, const N: usize> FoldMappable<A, J> for std::array::IntoIter<A, N> { + type Output<B, F> + = FoldMap<Self, A, B, J, F> + where + F: Fn(J, A) -> (J, B); #[inline] - fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F> { - FoldMap { iter : self, j, f } + fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F> { + FoldMap { iter: self, j, f } } } -impl<'a, A, const N : usize> IndexMappable<A> -for std::array::IntoIter<A, N> { - type Output<B, F> = IndexMap<Self, A, B, F> where F : Fn(usize, A) -> B; +impl<'a, A, const N: usize> IndexMappable<A> for std::array::IntoIter<A, N> { + type Output<B, F> + = IndexMap<Self, A, B, F> + where + F: Fn(usize, A) -> B; #[inline] - fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> Self::Output<B, F> { - IndexMap { iter : self, j : 0, f } + fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> Self::Output<B, F> { + IndexMap { + iter: self, + j: 0, + f, + } } } -impl<A, J : Copy, const N : usize> FoldMappable<A, J> for [A; N] { - type Output<B, F> = [B; N] where F : Fn(J, A) -> (J, B); +impl<A, J: Copy, const N: usize> FoldMappable<A, J> for [A; N] { + type Output<B, F> + = [B; N] + where + F: Fn(J, A) -> (J, B); #[inline] - fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> [B; N] { + fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> [B; N] { // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; // let mut res = MaybeUninit::uninit_array::<N>(); // for (a, i) in self.into_iter().zip(0..N) { @@ -292,10 +318,13 @@ } } -impl<A, const N : usize> IndexMappable<A> for [A; N] { - type Output<B, F> = [B; N] where F : Fn(usize, A) -> B; +impl<A, const N: usize> IndexMappable<A> for [A; N] { + type Output<B, F> + = [B; N] + where + F: Fn(usize, A) -> B; #[inline] - fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> [B; N] { + fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> [B; N] { // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; // let mut res = MaybeUninit::uninit_array::<N>(); // for (a, i) in self.into_iter().zip(0..N) { @@ -325,12 +354,9 @@ /// dropped. #[cfg(feature = "nightly")] #[inline] -pub(crate) fn collect_into_array_unchecked< - T, - I : Iterator<Item=T>, - const N: usize ->(mut iter: I) -> [T; N] -{ +pub(crate) fn collect_into_array_unchecked<T, I: Iterator<Item = T>, const N: usize>( + mut iter: I, +) -> [T; N] { if N == 0 { // SAFETY: An empty array is always inhabited and has no validity invariants. return unsafe { core::mem::zeroed() }; @@ -348,22 +374,28 @@ // SAFETY: this slice will contain only initialized objects. unsafe { - core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( - &mut self.array_mut.get_unchecked_mut(..self.initialized), - )); + for elem in self.array_mut.get_unchecked_mut(..self.initialized) { + elem.assume_init_drop(); + } } } } let mut array = MaybeUninit::uninit_array::<N>(); - let mut guard = Guard { array_mut: &mut array, initialized: 0 }; + let mut guard = Guard { + array_mut: &mut array, + initialized: 0, + }; while let Some(item) = iter.next() { // SAFETY: `guard.initialized` starts at 0, is increased by one in the // loop and the loop is aborted once it reaches N (which is // `array.len()`). unsafe { - guard.array_mut.get_unchecked_mut(guard.initialized).write(item); + guard + .array_mut + .get_unchecked_mut(guard.initialized) + .write(item); } guard.initialized += 1; @@ -383,12 +415,9 @@ #[cfg(not(feature = "nightly"))] #[inline] -pub(crate) fn collect_into_array_unchecked< - T, - I : Iterator<Item=T>, - const N: usize ->(iter: I) -> [T; N] -{ +pub(crate) fn collect_into_array_unchecked<T, I: Iterator<Item = T>, const N: usize>( + iter: I, +) -> [T; N] { match iter.collect::<Vec<T>>().try_into() { Ok(a) => a, Err(_) => panic!("collect_into_array failure: should not happen"), @@ -401,12 +430,12 @@ #[test] fn mapx_test() { - let a = [0,1,2]; - let mut b = [2,1,0]; - assert_eq!(map1(a, |x| x+1), [1,2,3]); - assert_eq!(map2(a, b, |x, y| x+y), [2,2,2]); - assert_eq!(map1_indexed(a, |i, y| y-i), [0,0,0]); - map1_indexed_mut(&mut b, |i, y| *y=i); + let a = [0, 1, 2]; + let mut b = [2, 1, 0]; + assert_eq!(map1(a, |x| x + 1), [1, 2, 3]); + assert_eq!(map2(a, b, |x, y| x + y), [2, 2, 2]); + assert_eq!(map1_indexed(a, |i, y| y - i), [0, 0, 0]); + map1_indexed_mut(&mut b, |i, y| *y = i); assert_eq!(b, a); } }