use std::net::SocketAddr;
use std::sync::Arc;
use async_trait::async_trait;
use aion_proto::generated;
use aion_store::NamespaceOrigin;
use super::route::{ForwardMintError, MintCredentials, MintForwarder, encode_mint_origin};
use crate::routing::{ForwardReply, ForwardRequest, RequestForwarder, owner_refusal};
#[derive(Clone)]
pub struct GrpcMintForwarder {
forwarder: Arc<dyn RequestForwarder>,
}
impl GrpcMintForwarder {
#[must_use]
pub const fn new(forwarder: Arc<dyn RequestForwarder>) -> Self {
Self { forwarder }
}
}
fn classify(status: &tonic::Status) -> ForwardMintError {
owner_refusal(status).map_or_else(
|| ForwardMintError::Unreachable(status.code().to_string()),
ForwardMintError::Refused,
)
}
#[async_trait]
impl MintForwarder for GrpcMintForwarder {
async fn forward_mint(
&self,
target: SocketAddr,
credentials: &MintCredentials,
namespaces: &[String],
origin: NamespaceOrigin,
) -> Result<(), ForwardMintError> {
let request = generated::MintNamespaceRequest {
namespaces: namespaces.to_vec(),
origin: encode_mint_origin(origin),
};
match self
.forwarder
.forward(
target,
credentials.to_grpc_metadata(),
ForwardRequest::MintNamespace(request),
)
.await
{
Ok(ForwardReply::MintNamespace(_)) => Ok(()),
Ok(_) => Err(ForwardMintError::Unreachable(
"the forwarder returned a reply for a different request".to_owned(),
)),
Err(status) => Err(classify(&status)),
}
}
}