use crate::{
any::{TypeName, WithContextLt},
bijective_higher_ranked_type,
effect::{Effect, Future},
hkt::AnySizedSend,
protocol::{walker::hint::HintMeta, Visitor},
Flow,
};
use super::VisitResult;
pub trait Sequence<'ctx, E: Effect> {
fn visit<'a>(
&'a mut self,
scope: DynSequenceScope<'a, 'ctx, E>,
) -> Future<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E>;
}
bijective_higher_ranked_type! {
pub type DynSequence['ctx][E]: WithContextLt['ctx][]
for<'a>
(dyn Sequence<'ctx, E> + Send + 'a)
where {
E: Effect
}
}
bijective_higher_ranked_type! {
pub type [][E]: TypeName[][]
for<'ctx>
(DynSequence<'ctx, E>)
where {
E: Effect
}
}
pub trait SequenceScope<'ctx, E: Effect> {
fn size_hint(&mut self) -> Future<'_, (usize, Option<usize>), E>;
fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E>;
}
pub type DynSequenceScope<'a, 'ctx, E> = &'a mut (dyn SequenceScope<'ctx, E> + Send + 'a);
bijective_higher_ranked_type! {
pub type SequenceKnownHkt[][]: AnySizedSend[][] for<'lt> (SequenceKnown)
}
#[derive(Default)]
pub struct SequenceKnown {
pub len: (usize, Option<usize>),
}
pub struct SequenceHint {
pub len: (usize, Option<usize>),
}
impl<'ctx, E: Effect> HintMeta<'ctx> for DynSequence<'ctx, E> {
type Known = SequenceKnownHkt;
type Hint = SequenceHint;
}
pub fn visit_sequence<'a, 'ctx, E: Effect>(
visitor: Visitor<'a, 'ctx>,
scope: DynSequenceScope<'a, 'ctx, E>,
) -> Future<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> {
if let Some(object) = visitor.upcast_mut::<DynSequence<'ctx, E>>() {
// Allow the visitor to give a hint if it wants.
object.visit(scope)
} else {
// If the visitor doesn't support request hint then we continue.
E::ready(VisitResult::Skipped(scope))
}
}