use dope_core::random;
use o3::{buffer::hold, depot::capacity};
use crate::{
life::session,
manifold::{
self,
client::{self, io},
schedule,
schedule::{Error, Report, Terminal, Turn},
stream,
},
};
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Activation<B> {
Keep,
Data(Option<B>),
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Disposition {
Keep,
Remove,
}
#[derive(Debug)]
pub enum Failure<E, K> {
Turn(E),
Idle(K),
Settle {
terminal: E,
error: K,
},
}
pub enum Settlement<E, K> {
Keep,
Remove,
Failed {
disposition: Disposition,
error: Failure<E, K>,
},
}
pub trait Driver<C, T>
where
C: client::Connection,
{
type Error;
fn data(
&mut self,
conn: &mut C,
key: C::Key,
value: &mut T,
) -> Result<Turn<C::Block>, Self::Error>;
fn settle(
&mut self,
conn: &mut C,
key: C::Key,
value: &mut T,
term: Terminal<Self::Error>,
) -> Settlement<Self::Error, C::Key>;
fn removed(&mut self, value: T);
}
pub trait Domain<C, T>
where
C: client::Connection,
{
fn capacity(&self) -> usize;
fn key_at(&self, index: usize) -> Option<C::Key>;
fn get(&self, stream: C::Key) -> Option<&T>;
fn get_mut(&mut self, stream: C::Key) -> Option<&mut T>;
fn remove(&mut self, stream: C::Key) -> Option<T>;
fn has_work(&self) -> bool;
fn try_insert(
&mut self,
stream: C::Key,
make: impl FnOnce() -> T,
) -> schedule::InsertResult<C::Key, ()>;
fn transaction<P, R, E>(
&mut self,
key: C::Key,
check: impl FnOnce(&T) -> Result<(Activation<C::Block>, P), E>,
commit: impl FnOnce(&mut T, P) -> R,
) -> Result<R, Error<E>>;
fn resume(&mut self, conn: &mut C, egress: schedule::Egress);
fn drive<D: Driver<C, T>>(
&mut self,
conn: &mut C,
driver: &mut D,
) -> Result<Report, Failure<D::Error, C::Key>>;
}
pub trait Plan<C: session::Storage>: Copy {
type Key: manifold::raw::Key;
type Block: Copy + Eq;
type Permit;
type Fields;
type Selection;
type Connection: client::Connection<
Owner = C,
Key = Self::Key,
Block = Self::Block,
Fields = Self::Fields,
Selection = Self::Selection,
Data: stream::Payload<C, Permit = Self::Permit>,
> + io::Read
+ io::Write;
type Domain<T>: Domain<Self::Connection, T>;
type Build;
type Storage;
const RETENTION: hold::Policy;
const MIN_PREFIX: usize;
fn open(self) -> Result<Self::Connection, Self::Build>;
fn open_seeded(self, seed: &random::Seed) -> Result<Self::Connection, Self::Build>;
fn domain<T>(cap: capacity::Count) -> Result<Self::Domain<T>, Self::Storage>;
}