From daf1cb6b084368567c580c2942c2da71fef676e2 Mon Sep 17 00:00:00 2001 From: Ivan Folgueira Bande Date: Fri, 22 Nov 2024 21:57:58 +0100 Subject: [PATCH] restoring back the type state pattern introduced by Richard --- examples/tic-tac-toe-gui/src/main.rs | 42 ++++++++++++------- waku-bindings/src/general/mod.rs | 1 - waku-bindings/src/lib.rs | 1 - waku-bindings/src/node/mod.rs | 61 ++++++++++++++++------------ 4 files changed, 63 insertions(+), 42 deletions(-) diff --git a/examples/tic-tac-toe-gui/src/main.rs b/examples/tic-tac-toe-gui/src/main.rs index 6ec6d87..bafc45e 100644 --- a/examples/tic-tac-toe-gui/src/main.rs +++ b/examples/tic-tac-toe-gui/src/main.rs @@ -7,7 +7,7 @@ use std::time::{SystemTime, Duration}; use tokio::sync::mpsc; use waku::{ waku_new, Encoding, Event, LibwakuResponse, WakuContentTopic, - WakuMessage, WakuNodeConfig, WakuNodeHandle, + WakuMessage, WakuNodeConfig, WakuNodeHandle, Initialized, Running }; #[derive(Serialize, Deserialize, PartialEq, Debug, Copy, Clone)] @@ -23,17 +23,17 @@ struct GameState { moves_left: usize, } -struct TicTacToeApp { +struct TicTacToeApp { game_state: Arc>, - waku: WakuNodeHandle, + waku: WakuNodeHandle, game_topic: &'static str, tx: mpsc::Sender, // Sender to send `msg` to main thread player_role: Option, // Store the player's role (X or O) } -impl TicTacToeApp { +impl TicTacToeApp { fn new( - waku: WakuNodeHandle, + waku: WakuNodeHandle, game_topic: &'static str, game_state: Arc>, tx: mpsc::Sender, @@ -47,10 +47,7 @@ impl TicTacToeApp { } } - fn start(&mut self) { - // Start the waku node - self.waku.start().expect("waku should start"); - + fn start(self) -> TicTacToeApp { let tx_clone = self.tx.clone(); let my_closure = move |response| { @@ -83,13 +80,18 @@ impl TicTacToeApp { }; // Establish a closure that handles the incoming messages - self.waku.ctx.waku_set_event_callback(my_closure).expect("set event call back working"); + self.waku.set_event_callback(my_closure).expect("set event call back working"); + + let _ = self.waku.version(); + + // Start the waku node + let waku = self.waku.start().expect("waku should start"); // Subscribe to desired topic using the relay protocol // self.waku.relay_subscribe(&self.game_topic.to_string()).expect("waku should subscribe"); let content_topic = WakuContentTopic::new("waku", "2", "tictactoegame", Encoding::Proto); - self.waku.filter_subscribe(&self.game_topic.to_string(), &content_topic.to_string()).expect("waku should subscribe"); + waku.filter_subscribe(&self.game_topic.to_string(), &content_topic.to_string()).expect("waku should subscribe"); // Connect to hard-coded node // let target_node_multi_addr = @@ -100,8 +102,18 @@ impl TicTacToeApp { // self.waku.connect(&target_node_multi_addr, None) // .expect("waku should connect to other node"); - } + TicTacToeApp { + game_state: self.game_state, + waku: waku, + game_topic: self.game_topic, + tx: self.tx, + player_role: self.player_role, + } + } +} + +impl TicTacToeApp { fn send_game_state(&self, game_state: &GameState) { let serialized_game_state = serde_json::to_string(game_state).unwrap(); let content_topic = WakuContentTopic::new("waku", "2", "tictactoegame", Encoding::Proto); @@ -193,7 +205,7 @@ impl TicTacToeApp { } } -impl eframe::App for TicTacToeApp { +impl eframe::App for TicTacToeApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { // Request a repaint every second @@ -325,9 +337,9 @@ async fn main() -> eframe::Result<()> { let shared_state = Arc::new(Mutex::new(game_state)); let clone = shared_state.clone(); - let mut app = TicTacToeApp::new(waku, game_topic, clone, tx); + let app = TicTacToeApp::new(waku, game_topic, clone, tx); - app.start(); + let app = app.start(); let clone = shared_state.clone(); // Listen for messages in the main thread diff --git a/waku-bindings/src/general/mod.rs b/waku-bindings/src/general/mod.rs index dea964a..dc0efb3 100644 --- a/waku-bindings/src/general/mod.rs +++ b/waku-bindings/src/general/mod.rs @@ -14,7 +14,6 @@ pub type WakuMessageVersion = usize; /// Waku message hash, hex encoded sha256 digest of the message pub type MessageHash = String; -/// Waku response, just a `Result` with an `String` error. pub type Result = std::result::Result; // TODO: Properly type and deserialize payload form base64 encoded string diff --git a/waku-bindings/src/lib.rs b/waku-bindings/src/lib.rs index 65a4f25..ee98013 100644 --- a/waku-bindings/src/lib.rs +++ b/waku-bindings/src/lib.rs @@ -17,7 +17,6 @@ use rln; pub use node::{ waku_create_content_topic, waku_destroy, waku_new, Event, Initialized, Key, Multiaddr, PublicKey, RLNConfig, Running, SecretKey, WakuMessageEvent, WakuNodeConfig, WakuNodeHandle, - WakuNodeContext, }; pub use general::{ diff --git a/waku-bindings/src/node/mod.rs b/waku-bindings/src/node/mod.rs index ac7590f..5ffcd1e 100644 --- a/waku-bindings/src/node/mod.rs +++ b/waku-bindings/src/node/mod.rs @@ -13,13 +13,15 @@ mod relay; pub use aes_gcm::Key; pub use multiaddr::Multiaddr; pub use secp256k1::{PublicKey, SecretKey}; +use std::marker::PhantomData; use std::time::Duration; // internal use crate::general::{MessageHash, Result, WakuMessage}; +use crate::utils::LibwakuResponse; +use crate::node::context::WakuNodeContext; pub use config::RLNConfig; pub use config::WakuNodeConfig; -pub use context::WakuNodeContext; pub use events::{Event, WakuMessageEvent}; pub use relay::waku_create_content_topic; @@ -27,48 +29,62 @@ use crate::Encoding; use crate::WakuContentTopic; use std::time::SystemTime; -/// Marker trait to disallow undesired waku node states in the handle -pub trait WakuNodeState {} - -/// Waku node initialized state +// Define state marker types pub struct Initialized; - -/// Waku node running state pub struct Running; -impl WakuNodeState for Initialized {} -impl WakuNodeState for Running {} - /// Handle to the underliying waku node -pub struct WakuNodeHandle { - pub ctx: WakuNodeContext, +pub struct WakuNodeHandle { + ctx: WakuNodeContext, + _state: PhantomData, } /// Spawn a new Waku node with the given configuration (default configuration if `None` provided) /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_newchar-jsonconfig) -pub fn waku_new(config: Option) -> Result { +pub fn waku_new(config: Option) -> Result> { Ok(WakuNodeHandle { ctx: management::waku_new(config)?, + _state: PhantomData, }) } -pub fn waku_destroy(node: WakuNodeHandle) -> Result<()> { +pub fn waku_destroy(node: WakuNodeHandle) -> Result<()> { management::waku_destroy(&node.ctx) } -// unsafe impl Send for WakuNodeHandle {} +impl WakuNodeHandle { + /// Get the nwaku version + pub fn version(&self) -> Result { + management::waku_version(&self.ctx) + } +} -impl WakuNodeHandle { +impl WakuNodeHandle { /// Start a Waku node mounting all the protocols that were enabled during the Waku node instantiation. /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_start) - pub fn start(&self) -> Result<()> { - management::waku_start(&self.ctx) + pub fn start(self) -> Result> { + management::waku_start(&self.ctx).map(|_| WakuNodeHandle { + ctx: self.ctx, + _state: PhantomData, + }) } + pub fn set_event_callback( + &self, + closure: F, + ) -> Result<()> { + self.ctx.waku_set_event_callback(closure) + } +} + +impl WakuNodeHandle { /// Stops a Waku node /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop) - pub fn stop(&self) -> Result<()> { - management::waku_stop(&self.ctx) + pub fn stop(self) -> Result> { + management::waku_stop(&self.ctx).map(|_| WakuNodeHandle { + ctx: self.ctx, + _state: PhantomData, + }) } /// Get the multiaddresses the Waku node is listening to @@ -77,11 +93,6 @@ impl WakuNodeHandle { management::waku_listen_addresses(&self.ctx) } - /// Get the nwaku version - pub fn version(&self) -> Result { - management::waku_version(&self.ctx) - } - /// Dial peer using a multiaddress /// If `timeout` as milliseconds doesn't fit into a `i32` it is clamped to [`i32::MAX`] /// If the function execution takes longer than `timeout` value, the execution will be canceled and an error returned.