diff --git a/native/native_rust_library/src/cxx_promise_manager.rs b/native/native_rust_library/src/cxx_promise_manager.rs new file mode 100644 --- /dev/null +++ b/native/native_rust_library/src/cxx_promise_manager.rs @@ -0,0 +1,69 @@ +use lazy_static::lazy_static; +use std::{collections::HashMap, future::Future, sync::Mutex}; +use tokio::sync::oneshot; + +lazy_static! { + pub static ref STRING_PROMISE_STORE: Mutex> = + Mutex::default(); + pub static ref UNIT_PROMISE_STORE: Mutex> = Mutex::default(); +} + +#[derive(Debug, Default)] +pub struct PromiseStore { + promises: HashMap>>, + next_id: usize, +} + +#[allow(unused)] +impl PromiseStore { + pub fn new_promise( + &mut self, + ) -> (usize, impl Future>) { + let id = self.next_id; + self.next_id += 1; + + let (tx, rx) = oneshot::channel(); + self.promises.insert(id, tx); + + let future = async move { + rx.await + .unwrap_or_else(|_| Err("Promise sender dropped".to_string())) + }; + + (id, future) + } + + pub fn resolve_promise(&mut self, id: usize, value: Result) { + let Some(tx) = self.promises.remove(&id) else { + return; + }; + let Ok(()) = tx.send(value) else { + // The receiver has beed dropped + return; + }; + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::thread; + + #[tokio::test] + async fn test_promises() { + const TEST_STR: &str = "success"; + + let (id, future) = STRING_PROMISE_STORE.lock().unwrap().new_promise(); + + thread::spawn(move || { + thread::sleep(std::time::Duration::from_millis(200)); + STRING_PROMISE_STORE + .lock() + .unwrap() + .resolve_promise(id, Ok(TEST_STR.to_string())); + }); + + let result = future.await; + assert_eq!(result, Ok(TEST_STR.to_string())); + } +} diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -18,6 +18,7 @@ use tracing::instrument; mod argon2_tools; +mod cxx_promise_manager; use argon2_tools::compute_backup_key; @@ -46,7 +47,6 @@ #[cxx::bridge] mod ffi { - extern "Rust" { #[cxx_name = "identityRegisterUser"] fn register_user(