use std::marker;
use dope_core::{
driver::route::{Identity, table::conn},
io::transfer,
};
use o3::buffer::hold::limits;
use crate::wire;
#[repr(transparent)]
pub struct Owner<W: wire::Spec, ID: Identity> {
storage: W::Storage<ID>,
}
impl<W: wire::Spec, ID: Identity> Owner<W, ID> {
pub const fn new(storage: W::Storage<ID>) -> Self {
Self { storage }
}
pub fn try_new(capacity: conn::Capacity) -> crate::Result<Self>
where
W::Bootstrap: Allocate<W>,
{
<W::Bootstrap as Allocate<W>>::try_storage::<ID>(capacity).map(Self::new)
}
pub fn bind<'d, P>(&'d self, plan: P) -> Result<Endpoint<'d, W, ID>, P::Error>
where
W: 'd,
ID: 'd,
P: Plan<W, ID>,
{
plan.bind(&self.storage).map(Endpoint::new)
}
}
pub trait Plan<W: wire::Spec, ID: Identity> {
type Error;
fn bind<'d>(self, storage: &'d W::Storage<ID>) -> Result<W::Binding<'d, ID>, Self::Error>
where
W: 'd,
ID: 'd;
}
#[repr(transparent)]
pub struct Local<'w, W: wire::Spec + 'w, ID: Identity + 'w> {
binding: W::Binding<'w, ID>,
}
impl<'w, W: wire::Spec + 'w, ID: Identity + 'w> Local<'w, W, ID> {
pub const fn new(binding: W::Binding<'w, ID>) -> Self {
Self { binding }
}
pub(crate) fn init<'d>(self, limits: Limits) -> W::Runtime<'w, 'd, ID>
where
W::Bootstrap: Init<W>,
'd: 'w,
{
<W::Bootstrap as Init<W>>::runtime::<'w, 'd, ID>(limits, self.binding)
}
}
#[repr(transparent)]
pub struct Endpoint<'w, W: wire::Spec + 'w, ID: Identity + 'w> {
binding: W::Binding<'w, ID>,
owner: marker::PhantomData<&'w W::Storage<ID>>,
}
impl<'w, W: wire::Spec + 'w, ID: Identity + 'w> Endpoint<'w, W, ID> {
fn new(binding: W::Binding<'w, ID>) -> Self {
Self {
binding,
owner: marker::PhantomData,
}
}
pub(crate) fn try_init<'d>(self, limits: Limits) -> crate::Result<W::Runtime<'w, 'd, ID>>
where
W::Bootstrap: Bootstrap<W>,
'd: 'w,
{
<W::Bootstrap as Bootstrap<W>>::try_runtime::<'w, 'd, ID>(limits, self.binding)
}
}
pub trait Allocate<W: wire::Spec> {
fn try_storage<ID: Identity>(capacity: conn::Capacity) -> crate::Result<W::Storage<ID>>;
}
pub trait Bootstrap<W: wire::Spec> {
fn try_runtime<'w, 'd, ID: Identity + 'w>(
limits: Limits,
binding: W::Binding<'w, ID>,
) -> crate::Result<W::Runtime<'w, 'd, ID>>
where
W: 'w,
'd: 'w;
}
pub trait Init<W: wire::Spec> {
fn runtime<'w, 'd, ID: Identity + 'w>(
limits: Limits,
binding: W::Binding<'w, ID>,
) -> W::Runtime<'w, 'd, ID>
where
W: 'w,
'd: 'w;
}
pub trait Reconfigure {
type Config;
fn reconfigure(&mut self, config: Self::Config);
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Limits {
connections: conn::Capacity,
retained: Retained,
resident: Resident,
len: transfer::NonZero,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct Retained(usize);
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct Resident(usize);
impl Limits {
pub(crate) const fn new(
cap: conn::Capacity,
retained: Retained,
resident: Resident,
len: transfer::NonZero,
) -> Self {
Self {
connections: cap,
retained,
resident,
len,
}
}
pub const fn fixed<
const CONNECTIONS: usize,
const RETAINED: usize,
const RESIDENT: usize,
const RECEIVE_LEN: u32,
>() -> Self {
Self {
connections: conn::Capacity::fixed::<CONNECTIONS>(),
retained: Retained(RETAINED),
resident: Resident(RESIDENT),
len: transfer::NonZero::fixed::<RECEIVE_LEN>(),
}
}
pub const fn connections(self) -> conn::Capacity {
self.connections
}
pub const fn retained(self) -> Retained {
self.retained
}
pub const fn resident(self) -> Resident {
self.resident
}
pub const fn receive_len(self) -> transfer::NonZero {
self.len
}
}
impl Retained {
pub const ZERO: Self = Self(0);
pub const fn into_raw(self) -> usize {
self.0
}
}
impl Resident {
pub const ZERO: Self = Self(0);
pub const fn from_limit(limit: limits::Bound) -> Self {
Self(limit.bytes())
}
pub const fn into_raw(self) -> usize {
self.0
}
}
impl From<usize> for Retained {
fn from(count: usize) -> Self {
Self(count)
}
}
impl From<usize> for Resident {
fn from(bytes: usize) -> Self {
Self(bytes)
}
}
const _: () = assert!(
std::mem::size_of::<Limits>()
== 2 * std::mem::size_of::<usize>() + 2 * std::mem::size_of::<u32>()
);