use phantom_type::PhantomType;
use crate::delivery::Delivery;
use crate::runtime::{self, AsyncRuntime};
pub trait Mpc: internal::Sealed {
type ProtocolMessage;
type Delivery: Delivery<
Self::ProtocolMessage,
SendError = Self::SendError,
ReceiveError = Self::ReceiveError,
>;
type Runtime: AsyncRuntime;
type SendError: core::error::Error + Send + Sync + 'static;
type ReceiveError: core::error::Error + Send + Sync + 'static;
fn into_party(self) -> MpcParty<Self::ProtocolMessage, Self::Delivery, Self::Runtime>;
}
mod internal {
pub trait Sealed {}
}
#[non_exhaustive]
pub struct MpcParty<M, D, R = runtime::DefaultRuntime> {
pub delivery: D,
pub runtime: R,
_msg: PhantomType<M>,
}
impl<M, D> MpcParty<M, D>
where
D: Delivery<M>,
{
pub fn connected(delivery: D) -> Self {
Self {
delivery,
runtime: Default::default(),
_msg: PhantomType::new(),
}
}
}
impl<M, D, X> MpcParty<M, D, X>
where
D: Delivery<M>,
{
pub fn map_delivery<D2>(self, f: impl FnOnce(D) -> D2) -> MpcParty<M, D2, X> {
let delivery = f(self.delivery);
MpcParty {
delivery,
runtime: self.runtime,
_msg: self._msg,
}
}
pub fn map_runtime<R>(self, f: impl FnOnce(X) -> R) -> MpcParty<M, D, R> {
let runtime = f(self.runtime);
MpcParty {
delivery: self.delivery,
runtime,
_msg: self._msg,
}
}
pub fn set_runtime<R>(self, runtime: R) -> MpcParty<M, D, R>
where
R: AsyncRuntime,
{
MpcParty {
delivery: self.delivery,
runtime,
_msg: self._msg,
}
}
}
impl<M, D, B> internal::Sealed for MpcParty<M, D, B> {}
impl<M, D, R> Mpc for MpcParty<M, D, R>
where
D: Delivery<M>,
D::SendError: core::error::Error + Send + Sync + 'static,
D::ReceiveError: core::error::Error + Send + Sync + 'static,
R: AsyncRuntime,
{
type ProtocolMessage = M;
type Delivery = D;
type Runtime = R;
type SendError = D::SendError;
type ReceiveError = D::ReceiveError;
fn into_party(self) -> MpcParty<Self::ProtocolMessage, Self::Delivery, Self::Runtime> {
self
}
}