use std::future::Future;
use super::{ExecutionContext, FailureKind, OperationDeclaration};
pub trait EndpointSet: Send + Sized + 'static {
fn empty() -> Option<Self> {
None
}
#[cfg(feature = "streaming")]
fn bind_wire(_limits: super::WireStreamLimits) -> Result<(Self, super::WireStreams), super::ServingError> {
Err(super::ServingError::StreamUnsupported)
}
fn item_types() -> (Option<std::any::TypeId>, Option<std::any::TypeId>);
fn transferred(&self) -> bool {
Self::item_types() != (None, None)
}
}
pub trait InputEndpoint: Send + Sized + 'static {
#[cfg(feature = "streaming")]
fn bind_wire(_limits: super::WireStreamLimits) -> Result<(Self, super::WireStreams), super::ServingError> {
Err(super::ServingError::StreamUnsupported)
}
type Item: Send + 'static;
fn transferred(&self) -> bool {
true
}
}
pub trait OutputEndpoint: Send + Sized + 'static {
#[cfg(feature = "streaming")]
fn bind_wire(_limits: super::WireStreamLimits) -> Result<(Self, super::WireStreams), super::ServingError> {
Err(super::ServingError::StreamUnsupported)
}
type Item: Send + 'static;
fn transferred(&self) -> bool {
true
}
}
#[doc(hidden)]
pub trait Carrier: Send + Sized + 'static {
type Declaration: OperationDeclaration;
type Error: std::error::Error + Send + Sync + 'static;
type StreamEndpoints: EndpointSet;
fn bind(context: ExecutionContext) -> impl Future<Output = Result<Self, Self::Error>> + Send;
fn attempt(
&mut self, context: ExecutionContext, request: &mut <Self::Declaration as OperationDeclaration>::Request,
endpoints: &mut Self::StreamEndpoints,
) -> impl Future<Output = Result<super::Response<<Self::Declaration as OperationDeclaration>::Response>, Self::Error>> + Send;
fn stop(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send {
async { Ok(()) }
}
fn cleanup(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send {
async { Ok(()) }
}
fn transferred(&self) -> bool {
false
}
fn classify(_error: &Self::Error) -> FailureKind {
FailureKind::Permanent
}
}
pub trait Executable: OperationDeclaration {
type Carrier: Carrier<Declaration = Self>;
const RESOURCES: &'static [super::Resource] = &[];
}
impl EndpointSet for () {
fn empty() -> Option<Self> {
Some(())
}
fn item_types() -> (Option<std::any::TypeId>, Option<std::any::TypeId>) {
(None, None)
}
}
impl<I: InputEndpoint, O: OutputEndpoint> EndpointSet for (I, O) {
#[cfg(feature = "streaming")]
fn bind_wire(limits: super::WireStreamLimits) -> Result<(Self, super::WireStreams), super::ServingError> {
let (input, incoming) = I::bind_wire(limits)?;
let (output, outgoing) = O::bind_wire(limits)?;
Ok(((input, output), incoming.combine(outgoing)))
}
fn transferred(&self) -> bool {
self.0.transferred() || self.1.transferred()
}
fn item_types() -> (Option<std::any::TypeId>, Option<std::any::TypeId>) {
(Some(std::any::TypeId::of::<I::Item>()), Some(std::any::TypeId::of::<O::Item>()))
}
}