aboutsummaryrefslogtreecommitdiff
path: root/src/message/signalproxy
diff options
context:
space:
mode:
authorMax Audron <audron@cocaine.farm>2021-11-29 14:18:30 +0100
committerMax Audron <audron@cocaine.farm>2021-11-29 14:27:09 +0100
commit6da4613578f1effb371f4f3dd6605c1dff16b0b7 (patch)
tree655c42ce4fa483d1db149d2f3db5cc37b558ab3f /src/message/signalproxy
parentadd NetworkList impl for CoreInfo (diff)
rework SyncProxy to use globally available channels
the SyncProxy is now a globally available OnceCell that transparently offers a struct with methods to send syncmessages and rpccalls. This allows me to get rid of the globally passed around syncproxy var. The Syncable trait provides default implementations that access this global so the library user usually does not need to use it directly. Further the Syncable trait now provides default implementations for it's methods and only a const for the CLASS name must be set. It isn't very idiomatic rust and takes away some freedom from the library user but i think that it's an overall nicer solution and simplifies the code big time.
Diffstat (limited to 'src/message/signalproxy')
-rw-r--r--src/message/signalproxy/initdata.rs5
-rw-r--r--src/message/signalproxy/mod.rs103
-rw-r--r--src/message/signalproxy/objects/aliasmanager.rs11
3 files changed, 76 insertions, 43 deletions
diff --git a/src/message/signalproxy/initdata.rs b/src/message/signalproxy/initdata.rs
index 9e54690..a391b4a 100644
--- a/src/message/signalproxy/initdata.rs
+++ b/src/message/signalproxy/initdata.rs
@@ -32,13 +32,14 @@ impl Deserialize for InitData {
res.remove(0);
let class_name: String = res.remove(0).into();
+ let object_name: String = res.remove(0).into();
Ok((
size,
Self {
class_name: class_name.clone(),
- object_name: res.remove(0).into(),
- init_data: Types::from_network(class_name.as_str(), &mut res),
+ object_name: object_name.clone(),
+ init_data: Types::from_network(class_name.as_str(), object_name.as_str(), &mut res),
},
))
}
diff --git a/src/message/signalproxy/mod.rs b/src/message/signalproxy/mod.rs
index b1e235a..9516105 100644
--- a/src/message/signalproxy/mod.rs
+++ b/src/message/signalproxy/mod.rs
@@ -24,39 +24,72 @@ pub use initrequest::*;
pub use rpccall::*;
pub use syncmessage::*;
+use once_cell::sync::OnceCell;
+
+pub static SYNC_PROXY: OnceCell<SyncProxy> = OnceCell::new();
+
+#[derive(Debug, Clone)]
+pub struct SyncProxy {
+ sync_channel: crossbeam_channel::Sender<SyncMessage>,
+ rpc_channel: crossbeam_channel::Sender<RpcCall>,
+}
+
/// SyncProxy sends sync and rpc messages
-pub trait SyncProxy {
+impl SyncProxy {
+ /// Initialize the global SYNC_PROXY object and return receiver ends for the SyncMessage and RpcCall channels
+ pub fn init(cap: usize) -> (crossbeam_channel::Receiver<SyncMessage>, crossbeam_channel::Receiver<RpcCall>) {
+ let (sync_tx, sync_rx) = crossbeam_channel::bounded(cap);
+ let (rpc_tx, rpc_rx) = crossbeam_channel::bounded(cap);
+
+ SYNC_PROXY.set(SyncProxy { sync_channel: sync_tx, rpc_channel: rpc_tx }).unwrap();
+
+ (sync_rx, rpc_rx)
+ }
+
+ /// Send a SyncMessage
fn sync(
&self,
class_name: &str,
object_name: Option<&str>,
function: &str,
params: VariantList,
- );
+ ) {
+ self.sync_channel.send(SyncMessage {
+ class_name: class_name.to_string(),
+ object_name: object_name.unwrap_or("").to_string(),
+ slot_name: function.to_string(),
+ params,
+ }).unwrap();
+ }
- /// Send a RpcCall
- fn rpc(&self, function: &str, params: VariantList);
+ /// Send an RpcCall
+ fn rpc(&self, function: &str, params: VariantList) {}
}
/// A base Syncable Object
+///
+/// Provides default implementations for sending SyncMessages and
+/// RpcCalls so you usually only have to set the CLASS const
pub trait Syncable {
+ /// The Class of the object as transmitted in the SyncMessage
+ const CLASS: &'static str;
+
/// Send a SyncMessage.
- ///
- /// Must implement a call to session.sync() that sets the class and object names
- ///
- /// Example:
- /// ```ignore
- /// impl Syncable for AliasManager {
- /// fn sync(&self, session: impl SyncProxy, function: &str, params: VariantList) {
- /// session.sync("AliasManager", None, function, params)
- /// }
- /// }
- /// ```
- fn send_sync(&self, session: impl SyncProxy, function: &str, params: VariantList);
+ fn send_sync(&self, object_name: Option<&str>, function: &str, params: VariantList) {
+ crate::message::signalproxy::SYNC_PROXY.get().unwrap().sync(
+ Self::CLASS,
+ object_name,
+ function,
+ params,
+ );
+ }
/// Send a RpcCall
- fn send_rpc(&self, session: impl SyncProxy, function: &str, params: VariantList) {
- session.rpc(function, params);
+ fn send_rpc(&self, function: &str, params: VariantList) {
+ crate::message::signalproxy::SYNC_PROXY
+ .get()
+ .unwrap()
+ .rpc(function, params);
}
}
@@ -65,18 +98,20 @@ pub trait StatefulSyncableServer: Syncable + translation::NetworkMap
where
Variant: From<<Self as translation::NetworkMap>::Item>,
{
- fn sync(&mut self, session: impl SyncProxy, mut msg: crate::message::SyncMessage)
+ fn sync(&mut self, mut msg: crate::message::SyncMessage)
where
Self: Sized,
{
match msg.slot_name.as_str() {
- "requestUpdate" => self.request_update(msg.params.pop().unwrap().try_into().unwrap()),
- _ => self.sync_custom(session, msg),
+ "requestUpdate" => StatefulSyncableServer::request_update(
+ self,
+ msg.params.pop().unwrap().try_into().unwrap(),
+ ),
+ _ => StatefulSyncableServer::sync_custom(self, msg),
}
}
- #[allow(unused_mut, unused_variables)]
- fn sync_custom(&mut self, session: impl SyncProxy, mut msg: crate::message::SyncMessage)
+ fn sync_custom(&mut self, mut msg: crate::message::SyncMessage)
where
Self: Sized,
{
@@ -86,11 +121,11 @@ where
}
/// Client -> Server: Update the whole object with received data
- fn update(&mut self, session: impl SyncProxy)
+ fn update(&mut self)
where
Self: Sized,
{
- self.send_sync(session, "update", vec![self.to_network_map().into()]);
+ self.send_sync(None, "update", vec![self.to_network_map().into()]);
}
/// Server -> Client: Update the whole object with received data
@@ -104,21 +139,25 @@ where
/// Methods for a Stateful Syncable object on the server side.
pub trait StatefulSyncableClient: Syncable + translation::NetworkMap {
- fn sync(&mut self, session: impl SyncProxy, mut msg: crate::message::SyncMessage)
+ fn sync(&mut self, mut msg: crate::message::SyncMessage)
where
Self: Sized,
{
match msg.slot_name.as_str() {
- "update" => self.update(msg.params.pop().unwrap().try_into().unwrap()),
- _ => self.sync_custom(session, msg),
+ "update" => {
+ StatefulSyncableClient::update(self, msg.params.pop().unwrap().try_into().unwrap())
+ }
+ _ => StatefulSyncableClient::sync_custom(self, msg),
}
}
- fn sync_custom(&mut self, _session: impl SyncProxy, _msg: crate::message::SyncMessage)
+ fn sync_custom(&mut self, msg: crate::message::SyncMessage)
where
Self: Sized,
{
- ()
+ match msg.slot_name.as_str() {
+ _ => (),
+ }
}
/// Client -> Server: Update the whole object with received data
@@ -130,11 +169,11 @@ pub trait StatefulSyncableClient: Syncable + translation::NetworkMap {
}
/// Server -> Client: Update the whole object with received data
- fn request_update(&mut self, session: impl SyncProxy)
+ fn request_update(&mut self)
where
Self: Sized,
{
- self.send_sync(session, "requestUpdate", vec![self.to_network_map().into()]);
+ self.send_sync(None, "requestUpdate", vec![self.to_network_map().into()]);
}
}
diff --git a/src/message/signalproxy/objects/aliasmanager.rs b/src/message/signalproxy/objects/aliasmanager.rs
index 61a68ce..3d8133a 100644
--- a/src/message/signalproxy/objects/aliasmanager.rs
+++ b/src/message/signalproxy/objects/aliasmanager.rs
@@ -35,7 +35,7 @@ impl StatefulSyncableClient for AliasManager {}
#[cfg(feature = "server")]
impl StatefulSyncableServer for AliasManager {
- fn sync_custom(&mut self, _session: impl SyncProxy, mut msg: crate::message::SyncMessage)
+ fn sync_custom(&mut self, mut msg: crate::message::SyncMessage)
where
Self: Sized,
{
@@ -49,14 +49,7 @@ impl StatefulSyncableServer for AliasManager {
}
impl Syncable for AliasManager {
- fn send_sync(
- &self,
- session: impl SyncProxy,
- function: &str,
- params: crate::primitive::VariantList,
- ) {
- session.sync("AliasManager", None, function, params)
- }
+ const CLASS: &'static str = "AliasManager";
}
/// Alias