use super::{
Endpoint, EndpointError, EndpointOp, EndpointResult, ErrorLocation, RecvResult, RouteBranch,
futures::{DecodeFuture, OfferFuture, RawOfferFuture, RawOfferLease},
};
use core::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
impl<'e, 'r, const ROLE: u8> RouteBranch<'e, 'r, ROLE> {
#[inline]
pub(crate) fn from_parts(endpoint: *mut Endpoint<'r, ROLE>, label: u8) -> Self {
Self {
endpoint,
label,
_borrow: core::marker::PhantomData,
_local_only: crate::local::LocalOnly::new(),
}
}
#[inline]
pub fn label(&self) -> u8 {
self.label
}
#[inline]
#[track_caller]
pub fn decode<M>(
self,
) -> impl core::future::Future<Output = EndpointResult<M::Decoded<'e>>> + use<'e, 'r, M, ROLE>
where
M: crate::g::Message,
{
DecodeFuture::<'e, 'r, ROLE, M>::new(self, ErrorLocation::caller())
}
}
impl<'r, const ROLE: u8> Drop for Endpoint<'r, ROLE> {
fn drop(&mut self) {
unsafe {
self.drop_kernel_endpoint();
}
}
}
impl<'e, 'r, const ROLE: u8> Drop for RouteBranch<'e, 'r, ROLE> {
fn drop(&mut self) {
unsafe {
(&mut *self.endpoint).restore_public_route_branch();
}
}
}
impl<'e, 'r, const ROLE: u8> RawOfferFuture<'e, 'r, ROLE> {
#[inline]
pub(super) fn new(endpoint: &'e mut Endpoint<'r, ROLE>) -> Self {
let endpoint_ptr = core::ptr::from_mut(endpoint);
let leased = unsafe { endpoint.init_public_offer_state() };
Self {
endpoint: endpoint_ptr,
lease: RawOfferLease::new(leased),
_borrow: core::marker::PhantomData,
}
}
#[inline]
pub(super) fn poll_raw(&mut self, cx: &mut Context<'_>) -> Poll<RecvResult<u8>> {
if self.lease.completed() {
panic!("completed offer future polled after Ready");
}
if !self.lease.leased() {
self.lease.mark_completed();
return Poll::Ready(Err(crate::endpoint::RecvError::PhaseInvariant));
}
match unsafe { (&mut *self.endpoint).poll_offer(cx) } {
Poll::Pending => Poll::Pending,
Poll::Ready(Err(err)) => {
self.lease.mark_completed();
Poll::Ready(Err(err))
}
Poll::Ready(Ok(label)) => {
self.lease.mark_completed();
Poll::Ready(Ok(label))
}
}
}
}
impl<'e, 'r, const ROLE: u8> OfferFuture<'e, 'r, ROLE> {
#[inline]
pub(super) fn new(endpoint: &'e mut Endpoint<'r, ROLE>, location: ErrorLocation) -> Self {
Self {
raw: RawOfferFuture::new(endpoint),
location,
}
}
}
impl<'e, 'r, const ROLE: u8> Future for OfferFuture<'e, 'r, ROLE> {
type Output = EndpointResult<RouteBranch<'e, 'r, ROLE>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
match this.raw.poll_raw(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(Err(err)) => Poll::Ready(Err(EndpointError::new(
EndpointOp::Offer,
this.location,
err,
))),
Poll::Ready(Ok(label)) => {
Poll::Ready(Ok(RouteBranch::from_parts(this.raw.endpoint, label)))
}
}
}
}
impl<'e, 'r, const ROLE: u8> Drop for RawOfferFuture<'e, 'r, ROLE> {
fn drop(&mut self) {
if self.lease.must_restore_on_drop() {
unsafe {
(&mut *self.endpoint).reset_public_offer_state();
}
}
}
}