use core::fmt;
use core::future::Future;
use crate::transport::{
AsyncExecutionError, AsyncResponseStaging, RawResponsePolicy, ResponseCompletion,
ResponseWriter, TransportRequest,
};
use super::AuthenticationScopePolicy;
#[derive(Clone, Copy)]
pub struct AuthenticatedRequest<'request, 'policy> {
request: TransportRequest<'request>,
policy: AuthenticationScopePolicy<'policy>,
response_policy: RawResponsePolicy<'policy>,
}
impl<'request, 'policy> AuthenticatedRequest<'request, 'policy> {
#[must_use]
pub const fn new(
request: TransportRequest<'request>,
policy: AuthenticationScopePolicy<'policy>,
response_policy: RawResponsePolicy<'policy>,
) -> Self {
Self {
request,
policy,
response_policy,
}
}
#[must_use]
pub const fn transport_request(self) -> TransportRequest<'request> {
self.request
}
#[must_use]
pub const fn policy(self) -> AuthenticationScopePolicy<'policy> {
self.policy
}
#[must_use]
pub const fn response_policy(self) -> RawResponsePolicy<'policy> {
self.response_policy
}
}
impl fmt::Debug for AuthenticatedRequest<'_, '_> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("AuthenticatedRequest")
.field("request", &self.request)
.field("policy", &self.policy)
.field("response_policy", &self.response_policy)
.finish()
}
}
pub trait BlockingAuthenticatedTransport {
type Error;
fn send_authenticated(
&self,
request: AuthenticatedRequest<'_, '_>,
response: &mut ResponseWriter<'_>,
) -> Result<(), Self::Error>;
}
pub trait AsyncAuthenticatedTransport {
type Error;
fn send_authenticated<'transport, 'request, 'policy, 'writer, 'buffer>(
&'transport self,
request: AuthenticatedRequest<'request, 'policy>,
response: AsyncResponseStaging<'writer, 'buffer>,
) -> impl Future<Output = Result<ResponseCompletion, Self::Error>> + Send + 'writer
where
'transport: 'writer,
'request: 'writer,
'policy: 'writer,
'buffer: 'writer;
}
pub trait LocalAsyncAuthenticatedTransport {
type Error;
fn send_authenticated_local<'transport, 'request, 'policy, 'writer, 'buffer>(
&'transport self,
request: AuthenticatedRequest<'request, 'policy>,
response: AsyncResponseStaging<'writer, 'buffer>,
) -> impl Future<Output = Result<ResponseCompletion, Self::Error>> + 'writer
where
'transport: 'writer,
'request: 'writer,
'policy: 'writer,
'buffer: 'writer;
}
pub async fn drive_local_authenticated<'transport, 'request, 'policy, 'writer, 'buffer, T>(
transport: &'transport T,
request: AuthenticatedRequest<'request, 'policy>,
response: &'writer mut ResponseWriter<'buffer>,
) -> Result<(), AsyncExecutionError<T::Error>>
where
T: LocalAsyncAuthenticatedTransport + ?Sized,
'transport: 'writer,
'request: 'writer,
'policy: 'writer,
'buffer: 'writer,
{
let mut attempt = response
.begin_attempt()
.map_err(AsyncExecutionError::Response)?;
let completion = transport
.send_authenticated_local(request, attempt.staging())
.await
.map_err(AsyncExecutionError::Transport)?;
attempt
.commit_completion(completion)
.map_err(AsyncExecutionError::Response)
}
pub async fn drive_async_authenticated<'transport, 'request, 'policy, 'writer, 'buffer, T>(
transport: &'transport T,
request: AuthenticatedRequest<'request, 'policy>,
response: &'writer mut ResponseWriter<'buffer>,
) -> Result<(), AsyncExecutionError<T::Error>>
where
T: AsyncAuthenticatedTransport + ?Sized,
'transport: 'writer,
'request: 'writer,
'policy: 'writer,
'buffer: 'writer,
{
let mut attempt = response
.begin_attempt()
.map_err(AsyncExecutionError::Response)?;
let completion = transport
.send_authenticated(request, attempt.staging())
.await
.map_err(AsyncExecutionError::Transport)?;
attempt
.commit_completion(completion)
.map_err(AsyncExecutionError::Response)
}
impl<T> LocalAsyncAuthenticatedTransport for T
where
T: AsyncAuthenticatedTransport + ?Sized,
{
type Error = T::Error;
async fn send_authenticated_local<'transport, 'request, 'policy, 'writer, 'buffer>(
&'transport self,
request: AuthenticatedRequest<'request, 'policy>,
response: AsyncResponseStaging<'writer, 'buffer>,
) -> Result<ResponseCompletion, Self::Error>
where
'transport: 'writer,
'request: 'writer,
'policy: 'writer,
'buffer: 'writer,
{
AsyncAuthenticatedTransport::send_authenticated(self, request, response).await
}
}