use std::cell::RefMut;
use std::marker::PhantomData;
use ref_cast::RefCast;
use sealed::sealed;
use super::HandoffId;
use crate::scheduled::graph::Hydroflow;
use crate::scheduled::handoff::{CanReceive, Handoff, TeeingHandoff, TryCanReceive};
#[sealed]
pub trait Polarity: 'static {}
#[expect(clippy::upper_case_acronyms, reason = "marker type")]
pub enum SEND {}
#[expect(clippy::upper_case_acronyms, reason = "marker type")]
pub enum RECV {}
#[sealed]
impl Polarity for SEND {}
#[sealed]
impl Polarity for RECV {}
#[must_use]
pub struct Port<S: Polarity, H>
where
H: Handoff,
{
pub(crate) handoff_id: HandoffId,
#[expect(clippy::type_complexity, reason = "phantom data")]
pub(crate) _marker: PhantomData<(*const S, fn() -> H)>,
}
pub type SendPort<H> = Port<SEND, H>;
pub type RecvPort<H> = Port<RECV, H>;
impl<T: Clone> RecvPort<TeeingHandoff<T>> {
pub fn tee(&self, hf: &mut Hydroflow) -> RecvPort<TeeingHandoff<T>> {
hf.teeing_handoff_tee(self)
}
pub fn drop(self, hf: &mut Hydroflow) {
hf.teeing_handoff_drop(self)
}
}
#[derive(RefCast)]
#[repr(transparent)]
pub struct PortCtx<S: Polarity, H> {
pub(crate) handoff: H,
pub(crate) _marker: PhantomData<*const S>,
}
pub type SendCtx<H> = PortCtx<SEND, H>;
pub type RecvCtx<H> = PortCtx<RECV, H>;
impl<H: Handoff> SendCtx<H> {
pub fn give<T>(&self, item: T) -> T
where
H: CanReceive<T>,
{
<H as CanReceive<T>>::give(&self.handoff, item)
}
pub fn try_give<T>(&self, item: T) -> Result<T, T>
where
H: TryCanReceive<T>,
{
<H as TryCanReceive<T>>::try_give(&self.handoff, item)
}
}
impl<H: Handoff> RecvCtx<H> {
pub fn take_inner(&self) -> H::Inner {
self.handoff.take_inner()
}
pub fn borrow_mut_swap(&self) -> RefMut<H::Inner> {
self.handoff.borrow_mut_swap()
}
}