use std::ops::ControlFlow;
use o3::{
buffer,
buffer::{hold, write::consume},
};
pub trait Cursor<'d, A>:
buffer::Complete + hold::raw::Retain<'d> + consume::Consume + buffer::raw::Consume + Sized
{
fn drive<T>(&mut self, done: T, use_head: &mut impl Use<'d, T>) -> T;
}
pub trait Head<'d>:
buffer::Complete + hold::raw::Retain<'d> + consume::Consume + buffer::raw::Consume
{
fn commit(self) -> usize;
}
pub trait Sequence<'d>:
buffer::Complete + hold::raw::Retain<'d> + consume::Consume + buffer::raw::Consume
{
type Head<'head>: Head<'d>
where
Self: 'head;
fn next(&mut self) -> Option<Self::Head<'_>>;
}
pub trait Use<'d, T> {
fn apply<R>(&mut self, head: &mut R) -> ControlFlow<T, T>
where
R: buffer::Complete + hold::raw::Retain<'d> + consume::Consume + buffer::raw::Consume;
}
pub struct Discard;
impl<'d> Use<'d, ()> for Discard {
fn apply<R>(&mut self, head: &mut R) -> ControlFlow<()>
where
R: buffer::Complete + hold::raw::Retain<'d> + consume::Consume + buffer::raw::Consume,
{
head.consume_max(usize::MAX);
ControlFlow::Continue(())
}
}
pub trait Drive<'d, R: buffer::Source>: Sized {
fn drive<T>(cursor: &mut R, done: T, use_head: &mut impl Use<'d, T>) -> T;
}
pub enum Direct {}
pub enum Segments {}
impl<'d, R: buffer::Complete + hold::raw::Retain<'d> + consume::Consume + buffer::raw::Consume>
Drive<'d, R> for Direct
{
fn drive<T>(cursor: &mut R, done: T, use_head: &mut impl Use<'d, T>) -> T {
if cursor.is_empty() {
return done;
}
match use_head.apply(cursor) {
ControlFlow::Continue(done) | ControlFlow::Break(done) => done,
}
}
}
impl<'d, R: buffer::Complete + hold::raw::Retain<'d> + consume::Consume + buffer::raw::Consume>
Cursor<'d, Direct> for R
{
fn drive<T>(&mut self, done: T, use_head: &mut impl Use<'d, T>) -> T {
Direct::drive(self, done, use_head)
}
}
impl<'d, R: Sequence<'d>> Drive<'d, R> for Segments {
fn drive<T>(cursor: &mut R, mut done: T, use_head: &mut impl Use<'d, T>) -> T {
loop {
let Some(mut head) = cursor.next() else {
return done;
};
let flow = use_head.apply(&mut head);
head.commit();
match flow {
ControlFlow::Continue(next) => done = next,
ControlFlow::Break(done) => return done,
}
}
}
}
impl<'d, R: Sequence<'d>> Cursor<'d, Segments> for R {
fn drive<T>(&mut self, done: T, use_head: &mut impl Use<'d, T>) -> T {
Segments::drive(self, done, use_head)
}
}