Skip to main content

hydro_lang/networking/
mod.rs

1//! Types for configuring network channels with serialization formats, transports, etc.
2
3use std::marker::PhantomData;
4
5use serde::Serialize;
6use serde::de::DeserializeOwned;
7
8use crate::live_collections::stream::networking::{deserialize_bincode, serialize_bincode};
9
10#[sealed::sealed]
11trait SerKind<T: ?Sized> {
12    fn serialize_thunk(is_demux: bool) -> syn::Expr;
13
14    fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr;
15}
16
17/// Serialize items using the [`bincode`] crate.
18pub enum Bincode {}
19
20#[sealed::sealed]
21impl<T: Serialize + DeserializeOwned> SerKind<T> for Bincode {
22    fn serialize_thunk(is_demux: bool) -> syn::Expr {
23        serialize_bincode::<T>(is_demux)
24    }
25
26    fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr {
27        deserialize_bincode::<T>(tagged)
28    }
29}
30
31/// An unconfigured serialization backend.
32pub enum NoSer {}
33
34#[sealed::sealed]
35trait TransportKind {}
36
37/// Send items across a length-delimited TCP channel.
38pub enum Tcp {}
39
40#[sealed::sealed]
41impl TransportKind for Tcp {}
42
43/// A networking backend implementation that supports items of type `T`.
44#[sealed::sealed]
45pub trait NetworkFor<T: ?Sized> {
46    /// Generates serialization logic for sending `T`.
47    fn serialize_thunk(is_demux: bool) -> syn::Expr;
48
49    /// Generates deserialization logic for receiving `T`.
50    fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr;
51
52    /// Returns the optional name of the network channel.
53    fn name(&self) -> Option<&str>;
54}
55
56/// A network channel configuration with `T` as transport backend and `S` as the serialization
57/// backend.
58pub struct NetworkingConfig<Tr: ?Sized, S: ?Sized, Name = ()> {
59    name: Option<Name>,
60    _phantom: (PhantomData<Tr>, PhantomData<S>),
61}
62
63impl<Tr: ?Sized, S: ?Sized> NetworkingConfig<Tr, S> {
64    /// Configures the network channel to use [`bincode`] to serialize items.
65    pub const fn bincode(self) -> NetworkingConfig<Tr, Bincode> {
66        NetworkingConfig {
67            name: self.name,
68            _phantom: (PhantomData, PhantomData),
69        }
70    }
71
72    /// Names the network channel and enables stable communication across multiple service versions.
73    pub fn name(self, name: impl Into<String>) -> NetworkingConfig<Tr, S, String> {
74        NetworkingConfig {
75            name: Some(name.into()),
76            _phantom: (PhantomData, PhantomData),
77        }
78    }
79}
80
81#[sealed::sealed]
82impl<Tr: ?Sized, S: ?Sized, T: ?Sized> NetworkFor<T> for NetworkingConfig<Tr, S>
83where
84    Tr: TransportKind,
85    S: SerKind<T>,
86{
87    fn serialize_thunk(is_demux: bool) -> syn::Expr {
88        S::serialize_thunk(is_demux)
89    }
90
91    fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr {
92        S::deserialize_thunk(tagged)
93    }
94
95    fn name(&self) -> Option<&str> {
96        None
97    }
98}
99
100#[sealed::sealed]
101impl<Tr: ?Sized, S: ?Sized, T: ?Sized> NetworkFor<T> for NetworkingConfig<Tr, S, String>
102where
103    Tr: TransportKind,
104    S: SerKind<T>,
105{
106    fn serialize_thunk(is_demux: bool) -> syn::Expr {
107        S::serialize_thunk(is_demux)
108    }
109
110    fn deserialize_thunk(tagged: Option<&syn::Type>) -> syn::Expr {
111        S::deserialize_thunk(tagged)
112    }
113
114    fn name(&self) -> Option<&str> {
115        self.name.as_deref()
116    }
117}
118
119/// A network channel that uses length-delimited TCP for transport.
120pub const TCP: NetworkingConfig<Tcp, NoSer> = NetworkingConfig {
121    name: None,
122    _phantom: (PhantomData, PhantomData),
123};