From 6da4613578f1effb371f4f3dd6605c1dff16b0b7 Mon Sep 17 00:00:00 2001 From: Max Audron Date: Mon, 29 Nov 2021 14:18:30 +0100 Subject: 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. --- src/message/signalproxy/mod.rs | 103 ++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 32 deletions(-) (limited to 'src/message/signalproxy/mod.rs') 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 = OnceCell::new(); + +#[derive(Debug, Clone)] +pub struct SyncProxy { + sync_channel: crossbeam_channel::Sender, + rpc_channel: crossbeam_channel::Sender, +} + /// 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, crossbeam_channel::Receiver) { + 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<::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()]); } } -- cgit v1.2.3 er'>2021-07-21rewrite network derive to work more consistentlyMax Audron-78/+90 this mainly ensures that the network and override_type / variant options work across the board 2021-07-21fix wrong capitalization for HighlightRuleListMax Audron-2/+2 2021-07-21implement the Network trait generically for all inner Variant TypesMax Audron-1/+66 2021-07-21change IRC MessageType to be a bitflag instead of enumMax Audron-54/+94 the BufferSyncer object uses this type in a bitflag manner to indicate all the kinds of change that happened. bitflag still allows very enum esque usage so the change is okay for the Message object. 2021-07-21fix network objectMax Audron-18/+24 2021-07-21minor docs and cleanupMax Audron-4/+8 2021-04-05WIP: impl more signalproxy objectsMax Audron-1000/+1621 2021-03-09WIP: impl signalproxy typesMax Audron-253/+376 2021-01-21add to and from network deriveMax Audron-42/+2767 2021-01-21reorganize tests and add quassel featuresMax Audron-551/+850 2021-01-04add example program: quasselproxyclientMax Audron-0/+280 and inspection proxy for quassel 2021-01-04random stuffMax Audron-2/+9 2021-01-04add more signalproxy objectsMax Audron-40/+120 2021-01-04add message parsing feature flagsMax Audron-43/+96 2021-01-04fix parsing of datetime when value is -1Max Audron-1/+9 2021-01-02update dependenciesMax Audron-267/+27 2021-01-02rework handshakemessage parsingMax Audron-141/+278 2020-10-16updateMax Audron-1553/+294 2020-10-16update paperworkMax Audron-487/+391