array_iterator/
lib.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![allow(clippy::tabs_in_doc_comments)]
16
17//! 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.
18//!
19//! ```
20//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
21//! 	std::array::IntoIter::new([a, b])
22//! }
23//! ```
24//!
25//! 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.
26//!
27//! Previous docs are below:
28//!
29//! ---
30//!
31//! Allows creating owning iterators out of arrays. This is useful for
32//! fixed-size iterators. Try writing the following function:
33//!
34//! ```compile_fail
35//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
36//! 	unimplemented!()
37//! }
38//! ```
39//!
40//! This is hard to do because most iterators don't own the values they are iterating over. One ugly solution is:
41//!
42//! ```
43//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
44//! 	Some(a).into_iter().chain(Some(b))
45//! }
46//!
47//! assert_eq!(pair_iter(1, 2).collect::<Vec<_>>(), &[1, 2]);
48//! ```
49//!
50//! This crate allows turning arrays into owning iterators, perfect for short, fixed-size iterators.
51//!
52//! ```
53//! use array_iterator::ArrayIterator;
54//!
55//! fn pair_iter(a: i32, b: i32) -> impl Iterator<Item=i32> {
56//! 	ArrayIterator::new([a, b])
57//! }
58//!
59//! assert_eq!(pair_iter(1, 2).collect::<Vec<_>>(), &[1, 2]);
60//! ```
61
62#[cfg(test)]mod tests;
63
64#[deprecated(since="Rust 1.51.0", note = "Use std::array::IntoIter instead.")]
65pub struct ArrayIterator<T, A: Array<T>> {
66	array: A::MaybeUninit,
67	alive: std::ops::Range<usize>,
68}
69
70impl<T, A: Array<T>> ArrayIterator<T, A> {
71	pub fn new(array: A) -> Self {
72		let array = array.into_maybeunint();
73		ArrayIterator {
74			alive: 0..array.as_ref().len(),
75			array,
76		}
77	}
78}
79
80impl <T, A: Array<T>> Iterator for ArrayIterator<T, A> {
81	type Item = T;
82
83	fn next(&mut self) -> Option<T> {
84		let i = self.alive.next()?;
85		let ptr = self.array.as_ref()[i].as_ptr();
86		Some(unsafe { ptr.read() })
87	}
88
89	fn size_hint(&self) -> (usize, Option<usize>) {
90		(self.len(), Some(self.len()))
91	}
92}
93
94impl<T, A: Array<T>> std::iter::ExactSizeIterator for ArrayIterator<T, A> {
95	fn len(&self) -> usize {
96		self.alive.len()
97	}
98}
99
100impl<T, A: Array<T>> std::iter::FusedIterator for ArrayIterator<T, A> { }
101
102impl<T: Clone, A: Array<T>> Clone for ArrayIterator<T, A> {
103	fn clone(&self) -> Self {
104		let mut array = unsafe { std::ptr::read(&self.array) };
105		for i in self.alive.clone() {
106			let srcptr = self.array.as_ref()[i].as_ptr();
107			let srcref = unsafe { &*srcptr };
108			let src = srcref.clone();
109
110			let dstptr = array.as_mut()[i].as_mut_ptr();
111			unsafe { dstptr.write(src) };
112		}
113
114		ArrayIterator {
115			array,
116			alive: self.alive.clone(),
117		}
118	}
119}
120
121impl<T, A: Array<T>> DoubleEndedIterator for ArrayIterator<T, A> {
122	fn next_back(&mut self) -> Option<Self::Item> {
123		let i = self.alive.next_back()?;
124		let ptr = self.array.as_ref()[i].as_ptr();
125		Some(unsafe { ptr.read() })
126	}
127}
128
129// https://github.com/rust-lang/rust/issues/37572
130// unsafe impl<T, A: Array<T>> std::iter::TrustedLen for ArrayIterator<T, A> { }
131
132impl<T, A: Array<T>> Drop for ArrayIterator<T, A> {
133	fn drop(&mut self) {
134		// We don't actually drop the array itself, just everything inside of it.
135		// Hopefully this is fine.
136		for _ in self {
137		}
138	}
139}
140
141/// Trait for array-like types that can be used as an iterator.
142///
143/// This is not intended for users to implement.
144///
145/// 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.
146#[deprecated(since="Rust 1.51.0", note = "Use std::array::IntoIter instead.")]
147pub trait Array<T> {
148	type MaybeUninit:
149		AsRef<[std::mem::MaybeUninit<T>]> +
150		AsMut<[std::mem::MaybeUninit<T>]>;
151
152	/// Convert to an array of MaybeUninit.
153	///
154	/// The return value **MUST** be completely initialized. If any of the values in the returned array are "uninit" then undefined behaviour **will** occur.
155	fn into_maybeunint(self) -> Self::MaybeUninit;
156}
157
158macro_rules! impl_array_for_arrays {
159	($($len:literal,)*) => {
160		$(
161			impl<T> Array<T> for [T; $len] {
162				type MaybeUninit = [std::mem::MaybeUninit<T>; $len];
163
164				fn into_maybeunint(self) -> Self::MaybeUninit {
165					// TODO: Implement into_maybeunint() using []::map() https://github.com/rust-lang/rust/issues/75243
166
167					// We can't use transmute here because rustc thinks that [T; N] and
168					// [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.
169
170					debug_assert_eq!(std::mem::size_of::<Self::MaybeUninit>(), std::mem::size_of::<Self>());
171
172					let partial = unsafe { std::mem::transmute_copy(&self) };
173					std::mem::forget(self);
174					partial
175				}
176			}
177		)*
178	}
179}
180
181impl_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,);