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
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// 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,);