如何使用 `NonNull` 为调整大小的数组堆栈实现 `Iterator`?

How to implement `Iterator` for a resizing array stack using `NonNull`?

我正在按照 guide 使用 NonNull:

实现调整大小的数组堆栈
pub struct ResizingStack<T> {
    a: NonNull<T>,
    n: usize,
    capacity: usize,
}

现在基本功能(例如 pushpop)运行良好。完整代码可见here。但是我在实现 Iterator 特征时遇到了一些麻烦。

对于 forward 迭代器,一个简单的解决方案是让 ResizingStack 强制并表现得像 slice.

impl<T> Deref for Vec<T> {
    type Target = [T];
    fn deref(&self) -> &[T] {
        unsafe {
            std::slice::from_raw_parts(self.a.as_ptr(), self.n)
        }
    }
}

然而,事实上,一个栈应该有一个backward迭代器。以下是我的尝试:

pub struct StackIter<'a, T> {
    buf: &'a ResizingStack<T>,
    index: usize,
}

impl<T> ResizingStack<T> {
    pub fn iter(&self) -> StackIter<'_, T> {
        StackIter {
            buf: self,
            index: self.n,
        }
    }
}

impl<'a, T> Iterator for StackIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index == 0 {
            None
        } else {
            let item;
            unsafe {
                item = Some(ptr::read(self.buf.a.as_ptr().add(self.index - 1)));
                self.index -= 1;
            }
            item // ERROR: expected `Option<&T>`, but found `Option<T>`.
        }
    }
}

没有必要对产生 &T.

的迭代器使用 unsafe 代码

这是一个使用 .split_last():

的解决方案
pub struct StackIter<'a, T> {
    buf: &'a [T],
}

impl<'a, T> Iterator for StackIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let (last, remainder) = self.buf.split_last()?;
        self.buf = remainder;
        Some(last)
    }
}

或者,这是一个包装 .rev():

的解决方案
use std::{iter::Rev, slice};

pub struct StackIter<'a, T> {
    inner: Rev<slice::Iter<'a, T>>,
}

impl<'a, T> Iterator for StackIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

在这一点上,我们不妨直接放弃包装器和 return 适配器:

impl<T> ResizingStack<T> {
    pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T> {
        self.deref().iter().rev()
    }
}