2023-08-19 21:44:27 +02:00
|
|
|
//! ### Instance
|
|
|
|
//!
|
|
|
|
//! This module provides convenience managers for the client instance
|
|
|
|
//!
|
|
|
|
//! the global instance reference is immutable and lazy-loaded, and requires `global` feature.
|
|
|
|
|
|
|
|
/// static global instance, allocated only if feature `global` is active
|
2023-08-19 04:36:59 +02:00
|
|
|
#[cfg(feature = "global")]
|
|
|
|
pub mod global {
|
2023-08-19 18:28:27 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2023-08-19 04:36:59 +02:00
|
|
|
lazy_static::lazy_static! {
|
2023-08-19 21:44:27 +02:00
|
|
|
/// the global instance of codemp session
|
2023-08-19 18:28:27 +02:00
|
|
|
pub static ref INSTANCE : super::a_sync::Instance = super::a_sync::Instance::default();
|
2023-08-19 04:36:59 +02:00
|
|
|
}
|
2023-08-16 23:09:47 +02:00
|
|
|
|
2023-08-19 18:28:27 +02:00
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
lazy_static::lazy_static! {
|
2023-08-19 21:44:27 +02:00
|
|
|
/// the global instance of codemp session
|
2023-08-19 18:28:27 +02:00
|
|
|
pub static ref INSTANCE : super::sync::Instance = super::sync::Instance::default();
|
2023-08-16 23:09:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-21 02:35:56 +02:00
|
|
|
#[cfg(feature = "global")]
|
2023-08-19 21:44:27 +02:00
|
|
|
pub use global::INSTANCE;
|
|
|
|
|
|
|
|
/// async implementation of session instance
|
2023-08-19 18:28:27 +02:00
|
|
|
pub mod a_sync {
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use tokio::sync::Mutex;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
buffer::controller::BufferController,
|
|
|
|
errors::Error, client::Client, cursor::controller::CursorController,
|
|
|
|
};
|
|
|
|
|
2023-08-19 21:44:27 +02:00
|
|
|
/// persistant session manager for codemp client
|
|
|
|
///
|
|
|
|
/// will hold a tokio mutex over an optional client, and drop its reference when disconnecting.
|
|
|
|
/// all methods are async because will await mutex availability
|
2023-08-19 18:28:27 +02:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Instance {
|
2023-08-19 21:44:27 +02:00
|
|
|
/// the tokio mutex containing a client, if connected
|
2023-08-19 18:28:27 +02:00
|
|
|
client: Mutex<Option<Client>>,
|
2023-08-19 04:36:59 +02:00
|
|
|
}
|
2023-08-19 18:28:27 +02:00
|
|
|
|
|
|
|
impl Instance {
|
2023-09-10 03:43:46 +02:00
|
|
|
/// connect to remote address instantiating a new client [crate::client::Client::new]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn connect(&self, addr: &str) -> crate::Result<()> {
|
2023-08-19 18:28:27 +02:00
|
|
|
*self.client.lock().await = Some(Client::new(addr).await?);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe version of [crate::client::Client::join]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn join(&self, session: &str) -> crate::Result<Arc<CursorController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.client
|
|
|
|
.lock().await
|
|
|
|
.as_mut()
|
|
|
|
.ok_or(Error::InvalidState { msg: "connect first".into() })?
|
|
|
|
.join(session)
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe version of [crate::client::Client::create]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn create(&self, path: &str, content: Option<&str>) -> crate::Result<()> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.client
|
|
|
|
.lock().await
|
|
|
|
.as_mut()
|
|
|
|
.ok_or(Error::InvalidState { msg: "connect first".into() })?
|
|
|
|
.create(path, content)
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe version of [crate::client::Client::attach]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn attach(&self, path: &str) -> crate::Result<Arc<BufferController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.client
|
|
|
|
.lock().await
|
|
|
|
.as_mut()
|
|
|
|
.ok_or(Error::InvalidState { msg: "connect first".into() })?
|
|
|
|
.attach(path)
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe version of [crate::client::Client::get_cursor]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn get_cursor(&self) -> crate::Result<Arc<CursorController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
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() })
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe version of [crate::client::Client::get_buffer]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn get_buffer(&self, path: &str) -> crate::Result<Arc<BufferController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
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() })
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe version of [crate::client::Client::leave_workspace]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn leave_workspace(&self) -> crate::Result<()> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.client
|
|
|
|
.lock().await
|
|
|
|
.as_mut()
|
|
|
|
.ok_or(Error::InvalidState { msg: "connect first".into() })?
|
|
|
|
.leave_workspace();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe version of [crate::client::Client::disconnect_buffer]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub async fn disconnect_buffer(&self, path: &str) -> crate::Result<bool> {
|
2023-08-19 18:28:27 +02:00
|
|
|
let res = self.client
|
|
|
|
.lock().await
|
|
|
|
.as_mut()
|
|
|
|
.ok_or(Error::InvalidState { msg: "connect first".into() })?
|
|
|
|
.disconnect_buffer(path);
|
|
|
|
Ok(res)
|
|
|
|
}
|
2023-08-16 23:09:47 +02:00
|
|
|
}
|
2023-08-19 18:28:27 +02:00
|
|
|
}
|
2023-08-16 23:09:47 +02:00
|
|
|
|
2023-08-19 21:44:27 +02:00
|
|
|
/// sync implementation of session instance
|
2023-08-19 18:28:27 +02:00
|
|
|
pub mod sync {
|
|
|
|
use std::sync::{Mutex, Arc};
|
2023-08-16 23:09:47 +02:00
|
|
|
|
2023-09-10 03:41:18 +02:00
|
|
|
use tokio::runtime::{Runtime, Handle};
|
2023-08-16 23:09:47 +02:00
|
|
|
|
2023-08-19 18:28:27 +02:00
|
|
|
use crate::{
|
|
|
|
client::Client, Error,
|
|
|
|
cursor::controller::CursorController,
|
|
|
|
buffer::controller::BufferController
|
|
|
|
};
|
2023-08-16 23:09:47 +02:00
|
|
|
|
2023-11-17 17:00:10 +01:00
|
|
|
/// persistent session manager for codemp client
|
2023-08-19 21:44:27 +02:00
|
|
|
///
|
|
|
|
/// will hold a std mutex over an optional client, and drop its reference when disconnecting.
|
|
|
|
/// also contains a tokio runtime to execute async futures on
|
|
|
|
/// all methods are wrapped on a runtime.block_on and thus sync
|
2023-08-19 18:28:27 +02:00
|
|
|
pub struct Instance {
|
2023-08-19 21:44:27 +02:00
|
|
|
/// the std mutex containing a client, if connected
|
2023-08-19 18:28:27 +02:00
|
|
|
client: Mutex<Option<Client>>,
|
2023-08-19 21:44:27 +02:00
|
|
|
/// the tokio runtime
|
2023-08-19 18:28:27 +02:00
|
|
|
runtime: Runtime,
|
2023-08-16 23:09:47 +02:00
|
|
|
}
|
2023-08-19 18:28:27 +02:00
|
|
|
|
|
|
|
impl Default for Instance {
|
|
|
|
fn default() -> Self {
|
|
|
|
Instance {
|
|
|
|
client: Mutex::new(None),
|
|
|
|
runtime: Runtime::new().expect("could not start tokio runtime"),
|
|
|
|
}
|
|
|
|
}
|
2023-08-19 04:02:21 +02:00
|
|
|
}
|
2023-08-19 18:28:27 +02:00
|
|
|
|
|
|
|
impl Instance {
|
2023-11-17 17:00:10 +01:00
|
|
|
fn if_client<T>(&self, op: impl FnOnce(&mut Client) -> T) -> crate::Result<T> {
|
2023-08-19 18:28:27 +02:00
|
|
|
if let Some(c) = self.client.lock().expect("client mutex poisoned").as_mut() {
|
|
|
|
Ok(op(c))
|
|
|
|
} else {
|
|
|
|
Err(Error::InvalidState { msg: "connect first".into() })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:44:27 +02:00
|
|
|
/// return a reference to contained tokio runtime, to spawn tasks on
|
2023-09-13 00:05:15 +02:00
|
|
|
pub fn rt(&self) -> &Handle { self.runtime.handle() }
|
2023-08-19 18:28:27 +02:00
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// connect and store a client session, threadsafe and sync version of [crate::client::Client::new]
|
2023-08-19 18:28:27 +02:00
|
|
|
pub fn connect(&self, addr: &str) -> Result<(), Error> {
|
|
|
|
*self.client.lock().expect("client mutex poisoned") = Some(self.rt().block_on(Client::new(addr))?);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe and sync version of [crate::client::Client::join]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub fn join(&self, session: &str) -> crate::Result<Arc<CursorController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.if_client(|c| self.rt().block_on(c.join(session)))?
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe and sync version of [crate::client::Client::create]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub fn create(&self, path: &str, content: Option<&str>) -> crate::Result<()> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.if_client(|c| self.rt().block_on(c.create(path, content)))?
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe and sync version of [crate::client::Client::attach]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub fn attach(&self, path: &str) -> crate::Result<Arc<BufferController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.if_client(|c| self.rt().block_on(c.attach(path)))?
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe and sync version of [crate::client::Client::get_cursor]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub fn get_cursor(&self) -> crate::Result<Arc<CursorController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.if_client(|c| c.get_cursor().ok_or(Error::InvalidState { msg: "join workspace first".into() }))?
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe and sync version of [crate::client::Client::get_buffer]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub fn get_buffer(&self, path: &str) -> crate::Result<Arc<BufferController>> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.if_client(|c| c.get_buffer(path).ok_or(Error::InvalidState { msg: "join workspace or create requested buffer first".into() }))?
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe and sync version of [crate::client::Client::leave_workspace]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub fn leave_workspace(&self) -> crate::Result<()> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.if_client(|c| c.leave_workspace())
|
|
|
|
}
|
|
|
|
|
2023-09-10 03:43:46 +02:00
|
|
|
/// threadsafe and sync version of [crate::client::Client::disconnect_buffer]
|
2023-11-17 17:00:10 +01:00
|
|
|
pub fn disconnect_buffer(&self, path: &str) -> crate::Result<bool> {
|
2023-08-19 18:28:27 +02:00
|
|
|
self.if_client(|c| c.disconnect_buffer(path))
|
|
|
|
}
|
2023-08-19 04:02:21 +02:00
|
|
|
}
|
2023-08-16 23:09:47 +02:00
|
|
|
}
|