Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::mem::{ManuallyDrop, zeroed};
- use std::ptr;
- const MAX_ARRAY_INTO_ITER_SIZE: usize = 8;
- #[derive(Clone)]
- struct ArrayIntoIter<T> {
- data: ManuallyDrop<[T; MAX_ARRAY_INTO_ITER_SIZE]>,
- len: usize,
- cur: usize,
- }
- impl<T> Iterator for ArrayIntoIter<T> {
- type Item = T;
- fn next(&mut self) -> Option<Self::Item> {
- if self.cur >= self.len {
- return None;
- }
- let idx = self.cur;
- self.cur += 1;
- Some(unsafe { ptr::read(self.data.get_unchecked_mut(idx)) })
- }
- }
- impl<T> Drop for ArrayIntoIter<T> {
- fn drop(&mut self) {
- unsafe {
- let elems = std::slice::from_raw_parts_mut(
- self.data.get_unchecked_mut(self.cur) as *mut T,
- self.len - self.cur
- );
- self.len = 0;
- self.cur = 0;
- std::ptr::drop_in_place(elems);
- }
- }
- }
- trait IntoIterator {
- type Item;
- type IntoIter: Iterator<Item = Self::Item>;
- fn into_iter(self) -> Self::IntoIter;
- }
- macro_rules! array_intoiter {
- ($($n:expr),+) => { $(
- impl<T> IntoIterator for [T; $n] {
- type Item = T;
- type IntoIter = ArrayIntoIter<T>;
- fn into_iter(self) -> Self::IntoIter {
- let len = self.len();
- ArrayIntoIter {
- data: ManuallyDrop::new(unsafe {
- let mut data: [T; MAX_ARRAY_INTO_ITER_SIZE] = zeroed();
- ptr::copy_nonoverlapping(self.as_ptr(), data.as_mut_ptr(), $n);
- data
- }),
- len,
- cur: 0,
- }
- }
- }
- )+ }
- }
- array_intoiter!(0, 1, 2, 3, 4, 5, 6, 7, 8);
- fn main() {
- // All perfectly safe code.
- let array: [&i32; 0] = [];
- let iter = array.into_iter();
- println!("{:?}", Some(iter).is_some());
- }
Add Comment
Please, Sign In to add comment