restoring back the type state pattern introduced by Richard

This commit is contained in:
Ivan Folgueira Bande 2024-11-22 21:57:58 +01:00
parent dad471a114
commit daf1cb6b08
No known key found for this signature in database
GPG Key ID: 3C117481F89E24A7
4 changed files with 63 additions and 42 deletions

View File

@ -7,7 +7,7 @@ use std::time::{SystemTime, Duration};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use waku::{ use waku::{
waku_new, Encoding, Event, LibwakuResponse, WakuContentTopic, waku_new, Encoding, Event, LibwakuResponse, WakuContentTopic,
WakuMessage, WakuNodeConfig, WakuNodeHandle, WakuMessage, WakuNodeConfig, WakuNodeHandle, Initialized, Running
}; };
#[derive(Serialize, Deserialize, PartialEq, Debug, Copy, Clone)] #[derive(Serialize, Deserialize, PartialEq, Debug, Copy, Clone)]
@ -23,17 +23,17 @@ struct GameState {
moves_left: usize, moves_left: usize,
} }
struct TicTacToeApp { struct TicTacToeApp<State> {
game_state: Arc<Mutex<GameState>>, game_state: Arc<Mutex<GameState>>,
waku: WakuNodeHandle, waku: WakuNodeHandle<State>,
game_topic: &'static str, game_topic: &'static str,
tx: mpsc::Sender<String>, // Sender to send `msg` to main thread tx: mpsc::Sender<String>, // Sender to send `msg` to main thread
player_role: Option<Player>, // Store the player's role (X or O) player_role: Option<Player>, // Store the player's role (X or O)
} }
impl TicTacToeApp { impl TicTacToeApp<Initialized> {
fn new( fn new(
waku: WakuNodeHandle, waku: WakuNodeHandle<Initialized>,
game_topic: &'static str, game_topic: &'static str,
game_state: Arc<Mutex<GameState>>, game_state: Arc<Mutex<GameState>>,
tx: mpsc::Sender<String>, tx: mpsc::Sender<String>,
@ -47,10 +47,7 @@ impl TicTacToeApp {
} }
} }
fn start(&mut self) { fn start(self) -> TicTacToeApp<Running> {
// Start the waku node
self.waku.start().expect("waku should start");
let tx_clone = self.tx.clone(); let tx_clone = self.tx.clone();
let my_closure = move |response| { let my_closure = move |response| {
@ -83,13 +80,18 @@ impl TicTacToeApp {
}; };
// Establish a closure that handles the incoming messages // 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 // Subscribe to desired topic using the relay protocol
// self.waku.relay_subscribe(&self.game_topic.to_string()).expect("waku should subscribe"); // self.waku.relay_subscribe(&self.game_topic.to_string()).expect("waku should subscribe");
let content_topic = WakuContentTopic::new("waku", "2", "tictactoegame", Encoding::Proto); 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 // Connect to hard-coded node
// let target_node_multi_addr = // let target_node_multi_addr =
@ -100,8 +102,18 @@ impl TicTacToeApp {
// self.waku.connect(&target_node_multi_addr, None) // self.waku.connect(&target_node_multi_addr, None)
// .expect("waku should connect to other node"); // .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<Running> {
fn send_game_state(&self, game_state: &GameState) { fn send_game_state(&self, game_state: &GameState) {
let serialized_game_state = serde_json::to_string(game_state).unwrap(); let serialized_game_state = serde_json::to_string(game_state).unwrap();
let content_topic = WakuContentTopic::new("waku", "2", "tictactoegame", Encoding::Proto); 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<Running> {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
// Request a repaint every second // Request a repaint every second
@ -325,9 +337,9 @@ async fn main() -> eframe::Result<()> {
let shared_state = Arc::new(Mutex::new(game_state)); let shared_state = Arc::new(Mutex::new(game_state));
let clone = shared_state.clone(); 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(); let clone = shared_state.clone();
// Listen for messages in the main thread // Listen for messages in the main thread

View File

@ -14,7 +14,6 @@ pub type WakuMessageVersion = usize;
/// Waku message hash, hex encoded sha256 digest of the message /// Waku message hash, hex encoded sha256 digest of the message
pub type MessageHash = String; pub type MessageHash = String;
/// Waku response, just a `Result` with an `String` error.
pub type Result<T> = std::result::Result<T, String>; pub type Result<T> = std::result::Result<T, String>;
// TODO: Properly type and deserialize payload form base64 encoded string // TODO: Properly type and deserialize payload form base64 encoded string

View File

@ -17,7 +17,6 @@ use rln;
pub use node::{ pub use node::{
waku_create_content_topic, waku_destroy, waku_new, Event, Initialized, Key, Multiaddr, waku_create_content_topic, waku_destroy, waku_new, Event, Initialized, Key, Multiaddr,
PublicKey, RLNConfig, Running, SecretKey, WakuMessageEvent, WakuNodeConfig, WakuNodeHandle, PublicKey, RLNConfig, Running, SecretKey, WakuMessageEvent, WakuNodeConfig, WakuNodeHandle,
WakuNodeContext,
}; };
pub use general::{ pub use general::{

View File

@ -13,13 +13,15 @@ mod relay;
pub use aes_gcm::Key; pub use aes_gcm::Key;
pub use multiaddr::Multiaddr; pub use multiaddr::Multiaddr;
pub use secp256k1::{PublicKey, SecretKey}; pub use secp256k1::{PublicKey, SecretKey};
use std::marker::PhantomData;
use std::time::Duration; use std::time::Duration;
// internal // internal
use crate::general::{MessageHash, Result, WakuMessage}; use crate::general::{MessageHash, Result, WakuMessage};
use crate::utils::LibwakuResponse;
use crate::node::context::WakuNodeContext;
pub use config::RLNConfig; pub use config::RLNConfig;
pub use config::WakuNodeConfig; pub use config::WakuNodeConfig;
pub use context::WakuNodeContext;
pub use events::{Event, WakuMessageEvent}; pub use events::{Event, WakuMessageEvent};
pub use relay::waku_create_content_topic; pub use relay::waku_create_content_topic;
@ -27,48 +29,62 @@ use crate::Encoding;
use crate::WakuContentTopic; use crate::WakuContentTopic;
use std::time::SystemTime; use std::time::SystemTime;
/// Marker trait to disallow undesired waku node states in the handle // Define state marker types
pub trait WakuNodeState {}
/// Waku node initialized state
pub struct Initialized; pub struct Initialized;
/// Waku node running state
pub struct Running; pub struct Running;
impl WakuNodeState for Initialized {}
impl WakuNodeState for Running {}
/// Handle to the underliying waku node /// Handle to the underliying waku node
pub struct WakuNodeHandle { pub struct WakuNodeHandle<State> {
pub ctx: WakuNodeContext, ctx: WakuNodeContext,
_state: PhantomData<State>,
} }
/// Spawn a new Waku node with the given configuration (default configuration if `None` provided) /// 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) /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_newchar-jsonconfig)
pub fn waku_new(config: Option<WakuNodeConfig>) -> Result<WakuNodeHandle> { pub fn waku_new(config: Option<WakuNodeConfig>) -> Result<WakuNodeHandle<Initialized>> {
Ok(WakuNodeHandle { Ok(WakuNodeHandle {
ctx: management::waku_new(config)?, ctx: management::waku_new(config)?,
_state: PhantomData,
}) })
} }
pub fn waku_destroy(node: WakuNodeHandle) -> Result<()> { pub fn waku_destroy(node: WakuNodeHandle<Initialized>) -> Result<()> {
management::waku_destroy(&node.ctx) management::waku_destroy(&node.ctx)
} }
// unsafe impl Send for WakuNodeHandle<Running> {} impl<State> WakuNodeHandle<State> {
/// Get the nwaku version
impl WakuNodeHandle { pub fn version(&self) -> Result<String> {
/// Start a Waku node mounting all the protocols that were enabled during the Waku node instantiation. management::waku_version(&self.ctx)
/// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_start) }
pub fn start(&self) -> Result<()> {
management::waku_start(&self.ctx)
} }
impl WakuNodeHandle<Initialized> {
/// 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<WakuNodeHandle<Running>> {
management::waku_start(&self.ctx).map(|_| WakuNodeHandle {
ctx: self.ctx,
_state: PhantomData,
})
}
pub fn set_event_callback<F: FnMut(LibwakuResponse) + 'static + Sync + Send>(
&self,
closure: F,
) -> Result<()> {
self.ctx.waku_set_event_callback(closure)
}
}
impl WakuNodeHandle<Running> {
/// Stops a Waku node /// Stops a Waku node
/// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop) /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop)
pub fn stop(&self) -> Result<()> { pub fn stop(self) -> Result<WakuNodeHandle<Initialized>> {
management::waku_stop(&self.ctx) management::waku_stop(&self.ctx).map(|_| WakuNodeHandle {
ctx: self.ctx,
_state: PhantomData,
})
} }
/// Get the multiaddresses the Waku node is listening to /// Get the multiaddresses the Waku node is listening to
@ -77,11 +93,6 @@ impl WakuNodeHandle {
management::waku_listen_addresses(&self.ctx) management::waku_listen_addresses(&self.ctx)
} }
/// Get the nwaku version
pub fn version(&self) -> Result<String> {
management::waku_version(&self.ctx)
}
/// Dial peer using a multiaddress /// Dial peer using a multiaddress
/// If `timeout` as milliseconds doesn't fit into a `i32` it is clamped to [`i32::MAX`] /// 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. /// If the function execution takes longer than `timeout` value, the execution will be canceled and an error returned.