From 4f3e09abd346a743883326030e2ab9880b5790b0 Mon Sep 17 00:00:00 2001 From: alemi Date: Sat, 19 Aug 2023 04:36:59 +0200 Subject: [PATCH] feat: instance is sync and way more elegant --- Cargo.toml | 4 +- src/instance.rs | 107 +++++++++++++++++------------------------------- src/lib.rs | 5 +-- 3 files changed, 40 insertions(+), 76 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f57700e..bb42113 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,6 @@ lazy_static = { version = "1.4", optional = true } tonic-build = "0.9" [features] -default = ["proto", "static"] +default = ["proto", "global"] proto = ["dep:prost"] -static = ["dep:lazy_static"] +global = ["dep:lazy_static"] diff --git a/src/instance.rs b/src/instance.rs index a31eb13..28439fc 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1,106 +1,73 @@ -use std::sync::Arc; +use std::sync::{Arc, Mutex}; -use tokio::sync::Mutex; +use tokio::runtime::Runtime; use crate::{ buffer::controller::BufferController, errors::Error, client::Client, cursor::controller::CursorController, }; - -use tokio::runtime::Runtime; - -lazy_static::lazy_static! { - pub static ref RUNTIME : Runtime = Runtime::new().expect("could not create tokio runtime"); - pub static ref INSTANCE : Instance = Instance::default(); +#[cfg(feature = "global")] +pub mod global { + lazy_static::lazy_static! { + pub static ref INSTANCE : super::Instance = super::Instance::default(); + } } pub struct Instance { client: Mutex>, + runtime: Runtime, } impl Default for Instance { fn default() -> Self { - Instance { client: Mutex::new(None) } + Instance { + client: Mutex::new(None), + runtime: Runtime::new().expect("could not start tokio runtime"), + } } } -// TODO these methods repeat a lot of code but Mutex makes it hard to simplify - impl Instance { - pub async fn connect(&self, addr: &str) -> Result<(), Error> { - *self.client.lock().await = Some(Client::new(addr).await?); + + fn if_client(&self, op: impl FnOnce(&mut Client) -> T) -> Result { + if let Some(c) = self.client.lock().expect("client mutex poisoned").as_mut() { + Ok(op(c)) + } else { + Err(Error::InvalidState { msg: "connect first".into() }) + } + } + + pub fn connect(&self, addr: &str) -> Result<(), Error> { + *self.client.lock().expect("client mutex poisoned") = Some(self.runtime.block_on(Client::new(addr))?); Ok(()) } - pub async fn join(&self, session: &str) -> Result, Error> { - self.client - .lock() - .await - .as_mut() - .ok_or(Error::InvalidState { msg: "connect first".into() })? - .join(session) - .await + pub fn join(&self, session: &str) -> Result, Error> { + self.if_client(|c| self.runtime.block_on(c.join(session)))? } - pub async fn create(&self, path: &str, content: Option<&str>) -> Result<(), Error> { - self.client - .lock() - .await - .as_mut() - .ok_or(Error::InvalidState { msg: "connect first".into() })? - .create(path, content) - .await + pub fn create(&self, path: &str, content: Option<&str>) -> Result<(), Error> { + self.if_client(|c| self.runtime.block_on(c.create(path, content)))? } - pub async fn attach(&self, path: &str) -> Result, Error> { - self.client - .lock() - .await - .as_mut() - .ok_or(Error::InvalidState { msg: "connect first".into() })? - .attach(path) - .await + pub fn attach(&self, path: &str) -> Result, Error> { + self.if_client(|c| self.runtime.block_on(c.attach(path)))? } - pub async fn get_cursor(&self) -> Result, Error> { - self.client - .lock() - .await - .as_mut() - .ok_or(Error::InvalidState { msg: "connect first".into() })? - .get_cursor() - .ok_or(Error::InvalidState { msg: "join a workspace first".into() }) + pub fn get_cursor(&self) -> Result, Error> { + self.if_client(|c| c.get_cursor().ok_or(Error::InvalidState { msg: "join workspace first".into() }))? } - pub async fn get_buffer(&self, path: &str) -> Result, Error> { - self.client - .lock() - .await - .as_mut() - .ok_or(Error::InvalidState { msg: "connect first".into() })? - .get_buffer(path) - .ok_or(Error::InvalidState { msg: "join a workspace or create requested buffer first".into() }) + pub fn get_buffer(&self, path: &str) -> Result, Error> { + self.if_client(|c| c.get_buffer(path).ok_or(Error::InvalidState { msg: "join workspace or create requested buffer first".into() }))? } - pub async fn leave_workspace(&self) -> Result<(), Error> { - self.client - .lock() - .await - .as_mut() - .ok_or(Error::InvalidState { msg: "connect first".into() })? - .leave_workspace(); - Ok(()) + pub fn leave_workspace(&self) -> Result<(), Error> { + self.if_client(|c| c.leave_workspace()) } - pub async fn disconnect_buffer(&self, path: &str) -> Result { - Ok( - self.client - .lock() - .await - .as_mut() - .ok_or(Error::InvalidState { msg: "connect first".into() })? - .disconnect_buffer(path) - ) + pub fn disconnect_buffer(&self, path: &str) -> Result { + self.if_client(|c| c.disconnect_buffer(path)) } } diff --git a/src/lib.rs b/src/lib.rs index e48eb28..718527b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,7 @@ pub mod cursor; -pub mod errors; pub mod buffer; - +pub mod errors; pub mod client; - -#[cfg(feature = "static")] pub mod instance; pub mod prelude;