array_iterator 1.8.0

Owning iterators based on arrays.
Documentation
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(clippy::tabs_in_doc_comments)]

//! This create is now deprecated as this functionality has been implemented in std since 1.15.0. Please use [`std::array::IntoIter::new`](https://doc.rust-lang.org/stable/std/array/struct.IntoIter.html) instead.
//!
//! ```
//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
//! 	std::array::IntoIter::new([a, b])
//! }
//! ```
//!
//! This crate will continue to receive bug and security fixes for the foreseeable future. No new features, docs or any other changes will be added.
//!
//! Previous docs are below:
//!
//! ---
//!
//! Allows creating owning iterators out of arrays. This is useful for
//! fixed-size iterators. Try writing the following function:
//!
//! ```compile_fail
//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
//! 	unimplemented!()
//! }
//! ```
//!
//! This is hard to do because most iterators don't own the values they are iterating over. One ugly solution is:
//!
//! ```
//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
//! 	Some(a).into_iter().chain(Some(b))
//! }
//!
//! assert_eq!(pair_iter(1, 2).collect::<Vec<_>>(), &[1, 2]);
//! ```
//!
//! This crate allows turning arrays into owning iterators, perfect for short, fixed-size iterators.
//!
//! ```
//! use array_iterator::ArrayIterator;
//!
//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
//! 	ArrayIterator::new([a, b])
//! }
//!
//! assert_eq!(pair_iter(1, 2).collect::<Vec<_>>(), &[1, 2]);
//! ```

#[cfg(test)]mod tests;

#[deprecated(since="Rust 1.51.0", note = "Use std::array::IntoIter instead.")]
pub struct ArrayIterator<T, A: Array<T>> {
	array: A::MaybeUninit,
	alive: std::ops::Range<usize>,
}

impl<T, A: Array<T>> ArrayIterator<T, A> {
	pub fn new(array: A) -> Self {
		let array = array.into_maybeunint();
		ArrayIterator {
			alive: 0..array.as_ref().len(),
			array,
		}
	}
}

impl <T, A: Array<T>> Iterator for ArrayIterator<T, A> {
	type Item = T;

	fn next(&mut self) -> Option<T> {
		let i = self.alive.next()?;
		let ptr = self.array.as_ref()[i].as_ptr();
		Some(unsafe { ptr.read() })
	}

	fn size_hint(&self) -> (usize, Option<usize>) {
		(self.len(), Some(self.len()))
	}
}

impl<T, A: Array<T>> std::iter::ExactSizeIterator for ArrayIterator<T, A> {
	fn len(&self) -> usize {
		self.alive.len()
	}
}

impl<T, A: Array<T>> std::iter::FusedIterator for ArrayIterator<T, A> { }

impl<T: Clone, A: Array<T>> Clone for ArrayIterator<T, A> {
	fn clone(&self) -> Self {
		let mut array = unsafe { std::ptr::read(&self.array) };
		for i in self.alive.clone() {
			let srcptr = self.array.as_ref()[i].as_ptr();
			let srcref = unsafe { &*srcptr };
			let src = srcref.clone();

			let dstptr = array.as_mut()[i].as_mut_ptr();
			unsafe { dstptr.write(src) };
		}

		ArrayIterator {
			array,
			alive: self.alive.clone(),
		}
	}
}

impl<T, A: Array<T>> DoubleEndedIterator for ArrayIterator<T, A> {
	fn next_back(&mut self) -> Option<Self::Item> {
		let i = self.alive.next_back()?;
		let ptr = self.array.as_ref()[i].as_ptr();
		Some(unsafe { ptr.read() })
	}
}

// https://github.com/rust-lang/rust/issues/37572
// unsafe impl<T, A: Array<T>> std::iter::TrustedLen for ArrayIterator<T, A> { }

impl<T, A: Array<T>> Drop for ArrayIterator<T, A> {
	fn drop(&mut self) {
		// We don't actually drop the array itself, just everything inside of it.
		// Hopefully this is fine.
		for _ in self {
		}
	}
}

/// Trait for array-like types that can be used as an iterator.
///
/// This is not intended for users to implement.
///
/// Furthermore this trait will be marked unsafe in the next major version. See https://gitlab.com/kevincox/array_iterator.rs/-/issues/1 for more details.
#[deprecated(since="Rust 1.51.0", note = "Use std::array::IntoIter instead.")]
pub trait Array<T> {
	type MaybeUninit:
		AsRef<[std::mem::MaybeUninit<T>]> +
		AsMut<[std::mem::MaybeUninit<T>]>;

	/// Convert to an array of MaybeUninit.
	///
	/// The return value **MUST** be completely initialized. If any of the values in the returned array are "uninit" then undefined behaviour **will** occur.
	fn into_maybeunint(self) -> Self::MaybeUninit;
}

macro_rules! impl_array_for_arrays {
	($($len:literal,)*) => {
		$(
			impl<T> Array<T> for [T; $len] {
				type MaybeUninit = [std::mem::MaybeUninit<T>; $len];

				fn into_maybeunint(self) -> Self::MaybeUninit {
					// TODO: Implement into_maybeunint() using []::map() https://github.com/rust-lang/rust/issues/75243

					// We can't use transmute here because rustc thinks that [T; N] and
					// [MaybeUninit<T>; N] are different sizes for some reason. However the two are guarenteed to have the same size and layout so this is fine.

					debug_assert_eq!(std::mem::size_of::<Self::MaybeUninit>(), std::mem::size_of::<Self>());

					let partial = unsafe { std::mem::transmute_copy(&self) };
					std::mem::forget(self);
					partial
				}
			}
		)*
	}
}

impl_array_for_arrays!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,);