chore: modularized crate into features

by default "client" is on so that it works like before but it's possible
to cherry pick features out and (for example) only build the grpc proto
structs
This commit is contained in:
əlemi 2023-09-10 03:40:31 +02:00
parent c0892b36cd
commit 4ec99bab36
5 changed files with 76 additions and 45 deletions

View file

@ -9,24 +9,31 @@ name = "codemp"
[dependencies]
# core
tracing = "0.1"
tonic = { version = "0.9", features = ["tls", "tls-roots"] }
# ot
operational-transform = { version = "0.6", features = ["serde"], optional = true }
# proto
tonic = { version = "0.9", features = ["tls", "tls-roots"], optional = true }
prost = { version = "0.11.8", optional = true }
md5 = "0.7.0"
uuid = { version = "1.3.1", features = ["v4"] }
operational-transform = { version = "0.6", features = ["serde"] }
tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "sync", "full"], optional = false }
tokio-stream = { version = "0.1", optional = false }
serde = { version = "1", optional = false }
serde_json = { version = "1", optional = false }
tracing-subscriber = { version = "0.3", optional = true }
similar = { version = "2.2", features = ["inline"] }
# api
similar = { version = "2.2", features = ["inline"], optional = true }
tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "sync", "full"], optional = true }
async-trait = { version = "0.1", optional = true }
# client
md5 = { version = "0.7.0", optional = true }
uuid = { version = "1.3.1", features = ["v4"], optional = true }
serde_json = { version = "1", optional = true }
tokio-stream = { version = "0.1", optional = true }
# global
lazy_static = { version = "1.4", optional = true }
[build-dependencies]
tonic-build = "0.9"
[features]
default = ["proto"]
proto = ["dep:prost"]
global = ["dep:lazy_static"]
sync = []
default = ["client"]
api = ["ot", "dep:similar", "dep:tokio", "dep:async-trait"]
ot = ["dep:operational-transform"]
proto = ["dep:prost", "dep:tonic"]
client = ["proto", "api", "dep:tokio", "dep:tokio-stream", "dep:uuid", "dep:md5", "dep:serde_json"]
global = ["client", "dep:lazy_static"]
sync = ["client"]

View file

@ -7,7 +7,7 @@ use crate::Result;
use std::sync::Arc;
use tokio::runtime::Runtime;
#[tonic::async_trait]
#[async_trait::async_trait]
pub(crate) trait ControllerWorker<T : Sized + Send + Sync> {
type Controller : Controller<T>;
type Tx;
@ -27,7 +27,7 @@ pub(crate) trait ControllerWorker<T : Sized + Send + Sync> {
/// * if possible, prefer a pure [Controller::recv] consumer
/// * a second possibility in preference is using a [Controller::callback]
/// * if neither is feasible a [Controller::poll]/[Controller::try_recv] approach is available
#[tonic::async_trait]
#[async_trait::async_trait]
pub trait Controller<T : Sized + Send + Sync> : Sized + Send + Sync {
/// type of upstream values, used in [Self::send]
type Input;

View file

@ -4,8 +4,6 @@
use std::{result::Result as StdResult, error::Error as StdError, fmt::Display};
use tokio::sync::{mpsc, broadcast, watch};
use tonic::{Status, Code};
use tracing::warn;
/// an error which can be ignored with just a warning entry
@ -51,7 +49,7 @@ pub type Result<T> = StdResult<T, Error>;
pub enum Error {
/// errors caused by tonic http layer
Transport {
status: Code,
status: String,
message: String,
},
/// errors caused by async channels
@ -81,34 +79,43 @@ impl Display for Error {
}
}
impl From<Status> for Error {
fn from(status: Status) -> Self {
Error::Transport { status: status.code(), message: status.message().to_string() }
#[cfg(feature = "client")]
impl From<tonic::Status> for Error {
fn from(status: tonic::Status) -> Self {
Error::Transport {
status: status.code().to_string(),
message: status.message().to_string()
}
}
}
#[cfg(feature = "client")]
impl From<tonic::transport::Error> for Error {
fn from(err: tonic::transport::Error) -> Self {
Error::Transport {
status: Code::Unknown, message: format!("underlying transport error: {:?}", err)
status: tonic::Code::Unknown.to_string(),
message: format!("underlying transport error: {:?}", err)
}
}
}
impl<T> From<mpsc::error::SendError<T>> for Error {
fn from(_value: mpsc::error::SendError<T>) -> Self {
#[cfg(feature = "client")]
impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error {
fn from(_value: tokio::sync::mpsc::error::SendError<T>) -> Self {
Error::Channel { send: true }
}
}
impl From<broadcast::error::RecvError> for Error {
fn from(_value: broadcast::error::RecvError) -> Self {
#[cfg(feature = "client")]
impl From<tokio::sync::broadcast::error::RecvError> for Error {
fn from(_value: tokio::sync::broadcast::error::RecvError) -> Self {
Error::Channel { send: false }
}
}
impl From<watch::error::RecvError> for Error {
fn from(_value: watch::error::RecvError) -> Self {
#[cfg(feature = "client")]
impl From<tokio::sync::watch::error::RecvError> for Error {
fn from(_value: tokio::sync::watch::error::RecvError) -> Self {
Error::Channel { send: false }
}
}

View file

@ -143,27 +143,33 @@
/// public traits exposed to clients
#[cfg(feature = "api")]
pub mod api;
/// cursor related types and controller
#[cfg(feature = "client")]
pub mod cursor;
/// buffer operations, factory, controller and types
#[cfg(feature = "client")]
pub mod buffer;
/// crate error types and helpers
pub mod errors;
/// underlying client session manager
#[cfg(feature = "client")]
pub mod client;
/// client wrapper to handle memory persistence
#[cfg(feature = "client")]
pub mod instance;
/// all-in-one imports : `use codemp::prelude::*;`
pub mod prelude;
/// underlying OperationalTransform library used, re-exported
#[cfg(feature = "ot")]
pub use operational_transform as ot;
/// protocol types and services auto-generated by grpc
@ -175,11 +181,12 @@ pub mod proto {
}
pub use api::Controller;
pub use client::Client;
pub use errors::Error;
pub use errors::Result;
#[cfg(feature = "sync")] pub use instance::sync::Instance;
#[cfg(not(feature = "sync"))] pub use instance::a_sync::Instance;
#[cfg(all(feature = "client", feature = "sync"))]
pub use instance::sync::Instance;
#[cfg(all(feature = "client", not(feature = "sync")))]
pub use instance::a_sync::Instance;

View file

@ -5,21 +5,31 @@
pub use crate::{
Error as CodempError,
Result as CodempResult,
};
Client as CodempClient,
#[cfg(feature = "ot")]
pub use crate::ot::OperationSeq as CodempOperationSeq;
#[cfg(feature = "api")]
pub use crate::{
api::Controller as CodempController,
api::OperationFactory as CodempOperationFactory,
};
#[cfg(feature = "client")]
pub use crate::{
client::Client as CodempClient,
cursor::Controller as CodempCursorController,
buffer::Controller as CodempBufferController,
ot::OperationSeq as CodempOperationSeq,
buffer::TextChange as CodempTextChange,
Instance as CodempInstance,
};
#[cfg(feature = "proto")]
pub use crate::{
proto::CursorPosition as CodempCursorPosition,
proto::CursorEvent as CodempCursorEvent,
proto::RowCol as CodempRowCol,
Instance as CodempInstance,
};
#[cfg(feature = "global")]