diff --git a/Cargo.toml b/Cargo.toml index bb42113..9369aee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,3 +29,4 @@ tonic-build = "0.9" default = ["proto", "global"] proto = ["dep:prost"] global = ["dep:lazy_static"] +sync = [] diff --git a/src/client.rs b/src/client.rs index 903833d..60c911b 100644 --- a/src/client.rs +++ b/src/client.rs @@ -42,6 +42,7 @@ impl Client { } pub fn leave_workspace(&mut self) { + // TODO need to stop tasks? self.workspace = None } diff --git a/src/instance.rs b/src/instance.rs index b7772be..fd5b481 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1,75 +1,171 @@ -use std::sync::{Arc, Mutex}; - -use tokio::runtime::Runtime; - -use crate::{ - buffer::controller::BufferController, - errors::Error, client::Client, cursor::controller::CursorController, -}; - #[cfg(feature = "global")] pub mod global { + #[cfg(not(feature = "sync"))] lazy_static::lazy_static! { - pub static ref INSTANCE : super::Instance = super::Instance::default(); + pub static ref INSTANCE : super::a_sync::Instance = super::a_sync::Instance::default(); + } + + #[cfg(feature = "sync")] + lazy_static::lazy_static! { + pub static ref INSTANCE : super::sync::Instance = super::sync::Instance::default(); } } -pub struct Instance { - client: Mutex>, - runtime: Runtime, -} +#[cfg(not(feature = "sync"))] +pub mod a_sync { + use std::sync::Arc; + + use tokio::sync::Mutex; + + use crate::{ + buffer::controller::BufferController, + errors::Error, client::Client, cursor::controller::CursorController, + }; -impl Default for Instance { - fn default() -> Self { - Instance { - client: Mutex::new(None), - runtime: Runtime::new().expect("could not start tokio runtime"), + #[derive(Default)] + pub struct Instance { + client: Mutex>, + } + + impl Instance { + pub async fn connect(&self, addr: &str) -> Result<(), Error> { + *self.client.lock().await = Some(Client::new(addr).await?); + 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 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 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 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 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 workspace 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 async fn disconnect_buffer(&self, path: &str) -> Result { + let res = self.client + .lock().await + .as_mut() + .ok_or(Error::InvalidState { msg: "connect first".into() })? + .disconnect_buffer(path); + Ok(res) } } } -impl Instance { +#[cfg(feature = "sync")] +pub mod sync { + use std::sync::{Mutex, Arc}; - 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() }) + use tokio::runtime::Runtime; + + use crate::{ + client::Client, Error, + cursor::controller::CursorController, + buffer::controller::BufferController + }; + + pub struct Instance { + client: Mutex>, + runtime: Runtime, + } + + impl Default for Instance { + fn default() -> Self { + Instance { + client: Mutex::new(None), + runtime: Runtime::new().expect("could not start tokio runtime"), + } } } - - pub fn rt(&self) -> &Runtime { &self.runtime } - - pub fn connect(&self, addr: &str) -> Result<(), Error> { - *self.client.lock().expect("client mutex poisoned") = Some(self.rt().block_on(Client::new(addr))?); - Ok(()) - } - - pub fn join(&self, session: &str) -> Result, Error> { - self.if_client(|c| self.rt().block_on(c.join(session)))? - } - - pub fn create(&self, path: &str, content: Option<&str>) -> Result<(), Error> { - self.if_client(|c| self.rt().block_on(c.create(path, content)))? - } - - pub fn attach(&self, path: &str) -> Result, Error> { - self.if_client(|c| self.rt().block_on(c.attach(path)))? - } - - pub fn get_cursor(&self) -> Result, Error> { - self.if_client(|c| c.get_cursor().ok_or(Error::InvalidState { msg: "join workspace 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 fn leave_workspace(&self) -> Result<(), Error> { - self.if_client(|c| c.leave_workspace()) - } - - pub fn disconnect_buffer(&self, path: &str) -> Result { - self.if_client(|c| c.disconnect_buffer(path)) + + impl Instance { + 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 rt(&self) -> &Runtime { &self.runtime } + + pub fn connect(&self, addr: &str) -> Result<(), Error> { + *self.client.lock().expect("client mutex poisoned") = Some(self.rt().block_on(Client::new(addr))?); + Ok(()) + } + + pub fn join(&self, session: &str) -> Result, Error> { + self.if_client(|c| self.rt().block_on(c.join(session)))? + } + + pub fn create(&self, path: &str, content: Option<&str>) -> Result<(), Error> { + self.if_client(|c| self.rt().block_on(c.create(path, content)))? + } + + pub fn attach(&self, path: &str) -> Result, Error> { + self.if_client(|c| self.rt().block_on(c.attach(path)))? + } + + pub fn get_cursor(&self) -> Result, Error> { + self.if_client(|c| c.get_cursor().ok_or(Error::InvalidState { msg: "join workspace 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 fn leave_workspace(&self) -> Result<(), Error> { + self.if_client(|c| c.leave_workspace()) + } + + pub fn disconnect_buffer(&self, path: &str) -> Result { + self.if_client(|c| c.disconnect_buffer(path)) + } } }