use alloc::{vec, vec::Vec};
#[cfg(nightly)]
use core::marker::PhantomData;
use core::{
fmt,
fmt::Formatter,
iter::FusedIterator,
slice::{Iter, IterMut},
};
use crate::Frame;
fn next<I: Iterator<Item = T>, T>(iter: &mut Vec<I>) -> Option<T> {
let out;
loop {
let last = iter.last_mut()?;
if let Some(next) = last.next() {
out = next;
break;
}
iter.pop();
}
Some(out)
}
#[must_use]
#[derive(Clone)]
pub struct Frames<'r> {
stack: Vec<Iter<'r, Frame>>,
}
impl<'r> Frames<'r> {
pub(crate) fn new(frames: &'r [Frame]) -> Self {
Self {
stack: vec![frames.iter()],
}
}
}
impl<'r> Iterator for Frames<'r> {
type Item = &'r Frame;
fn next(&mut self) -> Option<Self::Item> {
let frame = next(&mut self.stack)?;
self.stack.push(frame.sources().iter());
Some(frame)
}
}
impl<'r> FusedIterator for Frames<'r> {}
impl fmt::Debug for Frames<'_> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
fmt.debug_list().entries(self.clone()).finish()
}
}
#[must_use]
pub struct FramesMut<'r> {
stack: Vec<IterMut<'r, Frame>>,
}
impl<'r> FramesMut<'r> {
pub(crate) fn new(frames: &'r mut [Frame]) -> Self {
Self {
stack: vec![frames.iter_mut()],
}
}
}
impl<'r> Iterator for FramesMut<'r> {
type Item = &'r mut Frame;
fn next(&mut self) -> Option<Self::Item> {
let frame = next(&mut self.stack)?;
let frame: *mut Frame = frame;
unsafe {
self.stack.push((*frame).sources_mut().iter_mut());
Some(&mut *frame)
}
}
}
impl<'r> FusedIterator for FramesMut<'r> {}
#[must_use]
#[cfg(nightly)]
pub struct RequestRef<'r, T: ?Sized> {
frames: Frames<'r>,
_marker: PhantomData<&'r T>,
}
#[cfg(nightly)]
impl<'r, T: ?Sized> RequestRef<'r, T> {
pub(super) fn new(frames: &'r [Frame]) -> Self {
Self {
frames: Frames::new(frames),
_marker: PhantomData,
}
}
}
#[cfg(nightly)]
impl<'r, T> Iterator for RequestRef<'r, T>
where
T: ?Sized + 'static,
{
type Item = &'r T;
fn next(&mut self) -> Option<Self::Item> {
self.frames.by_ref().find_map(Frame::request_ref)
}
}
#[cfg(nightly)]
impl<'r, T> FusedIterator for RequestRef<'r, T> where T: ?Sized + 'static {}
#[cfg(nightly)]
impl<T: ?Sized> Clone for RequestRef<'_, T> {
fn clone(&self) -> Self {
Self {
frames: self.frames.clone(),
_marker: PhantomData,
}
}
}
#[cfg(nightly)]
impl<'r, T> fmt::Debug for RequestRef<'r, T>
where
T: ?Sized + fmt::Debug + 'static,
{
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
fmt.debug_list().entries(self.clone()).finish()
}
}
#[must_use]
#[cfg(nightly)]
pub struct RequestValue<'r, T> {
frames: Frames<'r>,
_marker: PhantomData<T>,
}
#[cfg(nightly)]
impl<'r, T> RequestValue<'r, T> {
pub(super) fn new(frames: &'r [Frame]) -> Self {
Self {
frames: Frames::new(frames),
_marker: PhantomData,
}
}
}
#[cfg(nightly)]
impl<'r, T> Iterator for RequestValue<'r, T>
where
T: 'static,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.frames.find_map(Frame::request_value)
}
}
#[cfg(nightly)]
impl<'r, T> FusedIterator for RequestValue<'r, T> where T: 'static {}
#[cfg(nightly)]
impl<T> Clone for RequestValue<'_, T> {
fn clone(&self) -> Self {
Self {
frames: self.frames.clone(),
_marker: PhantomData,
}
}
}
#[cfg(nightly)]
impl<'r, T> fmt::Debug for RequestValue<'r, T>
where
T: fmt::Debug + 'static,
{
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
fmt.debug_list().entries(self.clone()).finish()
}
}