use std::marker::PhantomData;
use serde::Serialize;
use serde::de::DeserializeOwned;
use crate::live_collections::stream::networking::{deserialize_bincode, serialize_bincode};
use crate::live_collections::stream::{NoOrder, TotalOrder};
use crate::nondet::NonDet;
#[sealed::sealed]
trait SerKind<T: ?Sized> {
fn serialize_thunk(is_demux: bool) -> syn::Expr;
fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr;
}
pub enum Bincode {}
#[sealed::sealed]
impl<T: Serialize + DeserializeOwned> SerKind<T> for Bincode {
fn serialize_thunk(is_demux: bool) -> syn::Expr {
serialize_bincode::<T>(is_demux)
}
fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr {
deserialize_bincode::<T>(tagged)
}
}
pub enum NoSer {}
#[sealed::sealed]
pub trait TransportKind {
type OrderingGuarantee: crate::live_collections::stream::Ordering;
fn networking_info() -> NetworkingInfo;
}
#[sealed::sealed]
#[diagnostic::on_unimplemented(
message = "TCP transport requires a failure policy. For example, `TCP.fail_stop()` stops sending messages after a failed connection."
)]
pub trait TcpFailPolicy {
type OrderingGuarantee: crate::live_collections::stream::Ordering;
fn tcp_fault() -> TcpFault;
}
pub enum FailStop {}
#[sealed::sealed]
impl TcpFailPolicy for FailStop {
type OrderingGuarantee = TotalOrder;
fn tcp_fault() -> TcpFault {
TcpFault::FailStop
}
}
pub enum Lossy {}
#[sealed::sealed]
impl TcpFailPolicy for Lossy {
type OrderingGuarantee = TotalOrder;
fn tcp_fault() -> TcpFault {
TcpFault::Lossy
}
}
pub enum LossyDelayedForever {}
#[sealed::sealed]
impl TcpFailPolicy for LossyDelayedForever {
type OrderingGuarantee = NoOrder;
fn tcp_fault() -> TcpFault {
TcpFault::LossyDelayedForever
}
}
pub struct Tcp<F> {
_phantom: PhantomData<F>,
}
#[sealed::sealed]
impl<F: TcpFailPolicy> TransportKind for Tcp<F> {
type OrderingGuarantee = F::OrderingGuarantee;
fn networking_info() -> NetworkingInfo {
NetworkingInfo::Tcp {
fault: F::tcp_fault(),
}
}
}
#[sealed::sealed]
pub trait NetworkFor<T: ?Sized> {
type OrderingGuarantee: crate::live_collections::stream::Ordering;
fn serialize_thunk(is_demux: bool) -> syn::Expr;
fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr;
fn name(&self) -> Option<&str>;
fn networking_info() -> NetworkingInfo;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize)]
pub enum TcpFault {
FailStop,
Lossy,
LossyDelayedForever,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
pub enum NetworkingInfo {
Tcp {
fault: TcpFault,
},
}
pub struct NetworkingConfig<Tr: ?Sized, S: ?Sized, Name = ()> {
name: Option<Name>,
_phantom: (PhantomData<Tr>, PhantomData<S>),
}
impl<Tr: ?Sized, S: ?Sized> NetworkingConfig<Tr, S> {
pub fn name(self, name: impl Into<String>) -> NetworkingConfig<Tr, S, String> {
NetworkingConfig {
name: Some(name.into()),
_phantom: (PhantomData, PhantomData),
}
}
}
impl<Tr: ?Sized, N> NetworkingConfig<Tr, NoSer, N> {
pub const fn bincode(mut self) -> NetworkingConfig<Tr, Bincode, N> {
let taken_name = self.name.take();
std::mem::forget(self); NetworkingConfig {
name: taken_name,
_phantom: (PhantomData, PhantomData),
}
}
}
impl<S: ?Sized> NetworkingConfig<Tcp<()>, S> {
pub const fn fail_stop(self) -> NetworkingConfig<Tcp<FailStop>, S> {
NetworkingConfig {
name: self.name,
_phantom: (PhantomData, PhantomData),
}
}
pub const fn lossy(self, nondet: NonDet) -> NetworkingConfig<Tcp<Lossy>, S> {
let _ = nondet;
NetworkingConfig {
name: self.name,
_phantom: (PhantomData, PhantomData),
}
}
pub const fn lossy_delayed_forever(self) -> NetworkingConfig<Tcp<LossyDelayedForever>, S> {
NetworkingConfig {
name: self.name,
_phantom: (PhantomData, PhantomData),
}
}
}
#[sealed::sealed]
impl<Tr: ?Sized, S: ?Sized, T: ?Sized> NetworkFor<T> for NetworkingConfig<Tr, S>
where
Tr: TransportKind,
S: SerKind<T>,
{
type OrderingGuarantee = Tr::OrderingGuarantee;
fn serialize_thunk(is_demux: bool) -> syn::Expr {
S::serialize_thunk(is_demux)
}
fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr {
S::deserialize_thunk(tagged)
}
fn name(&self) -> Option<&str> {
None
}
fn networking_info() -> NetworkingInfo {
Tr::networking_info()
}
}
#[sealed::sealed]
impl<Tr: ?Sized, S: ?Sized, T: ?Sized> NetworkFor<T> for NetworkingConfig<Tr, S, String>
where
Tr: TransportKind,
S: SerKind<T>,
{
type OrderingGuarantee = Tr::OrderingGuarantee;
fn serialize_thunk(is_demux: bool) -> syn::Expr {
S::serialize_thunk(is_demux)
}
fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr {
S::deserialize_thunk(tagged)
}
fn name(&self) -> Option<&str> {
self.name.as_deref()
}
fn networking_info() -> NetworkingInfo {
Tr::networking_info()
}
}
pub const TCP: NetworkingConfig<Tcp<()>, NoSer> = NetworkingConfig {
name: None,
_phantom: (PhantomData, PhantomData),
};