From 490a54d55936f2f2a1bee561df4009db8d39240b Mon Sep 17 00:00:00 2001 From: Zixuan Chen Date: Tue, 21 Mar 2023 10:50:18 +0800 Subject: [PATCH] feat: expose from loro crate --- .vscode/settings.json | 5 +- Cargo.lock | 3 + crates/loro-internal/src/container.rs | 3 +- .../src/container/list/list_container.rs | 3 + crates/loro-internal/src/event.rs | 4 +- crates/loro-internal/src/hierarchy.rs | 16 ++- .../loro-internal/src/log_store/encoding.rs | 4 +- crates/loro-internal/src/log_store/import.rs | 2 +- crates/loro-internal/src/loro.rs | 2 +- crates/loro-internal/src/transaction.rs | 5 + crates/loro/Cargo.toml | 1 + crates/loro/src/lib.rs | 111 ++++++++++++++++-- crates/loro/tests/test.rs | 17 +++ 13 files changed, 152 insertions(+), 24 deletions(-) create mode 100644 crates/loro/tests/test.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index 55afda20..3a40cccf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,7 +21,10 @@ "rust-analyzer.runnableEnv": { "RUST_BACKTRACE": "full" }, - "rust-analyzer.cargo.features": ["test_utils", "wasm"], + "rust-analyzer.cargo.features": [ + "loro-internal/test_utils", + "loro-internal/wasm" + ], "editor.defaultFormatter": "rust-lang.rust-analyzer", "editor.formatOnSave": true, "todo-tree.general.tags": [ diff --git a/Cargo.lock b/Cargo.lock index 97ab2066..de4b1702 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -747,6 +747,9 @@ dependencies = [ [[package]] name = "loro" version = "0.1.0" +dependencies = [ + "loro-internal", +] [[package]] name = "loro-ffi" diff --git a/crates/loro-internal/src/container.rs b/crates/loro-internal/src/container.rs index 33104447..6c65647d 100644 --- a/crates/loro-internal/src/container.rs +++ b/crates/loro-internal/src/container.rs @@ -21,7 +21,7 @@ use std::{ fmt::{Debug, Display}, }; -use self::{pool_mapping::StateContent, registry::ContainerIdx}; +use self::pool_mapping::StateContent; pub mod pool_mapping; pub mod registry; @@ -31,6 +31,7 @@ pub mod map; mod pool; pub mod text; +pub use registry::ContainerIdx; // Note: It will be encoded into binary format, so the order of its fields should not be changed. #[cfg_attr(feature = "test_utils", derive(arbitrary::Arbitrary))] #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Serialize, Deserialize)] diff --git a/crates/loro-internal/src/container/list/list_container.rs b/crates/loro-internal/src/container/list/list_container.rs index 698195fd..e366f498 100644 --- a/crates/loro-internal/src/container/list/list_container.rs +++ b/crates/loro-internal/src/container/list/list_container.rs @@ -775,6 +775,7 @@ mod test { } #[test] + #[cfg(feature = "json")] fn collection() { let mut loro = LoroCore::default(); let mut list = loro.get_list("list"); @@ -798,6 +799,7 @@ mod test { } #[test] + #[cfg(feature = "json")] fn for_each() { let mut loro = LoroCore::default(); let mut list = loro.get_list("list"); @@ -816,6 +818,7 @@ mod test { } #[test] + #[cfg(feature = "json")] fn map() { let mut loro = LoroCore::default(); let mut list = loro.get_list("list"); diff --git a/crates/loro-internal/src/event.rs b/crates/loro-internal/src/event.rs index 5bd8e35c..4e576509 100644 --- a/crates/loro-internal/src/event.rs +++ b/crates/loro-internal/src/event.rs @@ -11,7 +11,7 @@ use crate::{ }; #[derive(Debug)] -pub struct RawEvent { +pub(crate) struct RawEvent { pub container_id: ContainerID, pub old_version: Frontiers, pub new_version: Frontiers, @@ -79,7 +79,7 @@ impl ObserverOptions { pub type ObserverHandler = Box; -pub struct Observer { +pub(crate) struct Observer { handler: ObserverHandler, options: ObserverOptions, } diff --git a/crates/loro-internal/src/hierarchy.rs b/crates/loro-internal/src/hierarchy.rs index bcb43b5e..09fe66fe 100644 --- a/crates/loro-internal/src/hierarchy.rs +++ b/crates/loro-internal/src/hierarchy.rs @@ -147,12 +147,16 @@ impl Hierarchy { } #[inline(always)] - pub fn get_abs_path(&self, reg: &ContainerRegistry, descendant: &ContainerID) -> Option { + pub(crate) fn get_abs_path( + &self, + reg: &ContainerRegistry, + descendant: &ContainerID, + ) -> Option { let path = self.get_path(reg, descendant, None); path.and_then(|x| if x.is_empty() { None } else { Some(x) }) } - pub fn get_path( + pub(crate) fn get_path( &self, reg: &ContainerRegistry, descendant: &ContainerID, @@ -208,7 +212,7 @@ impl Hierarchy { Some(path) } - pub fn should_notify(&self, container_id: &ContainerID) -> bool { + pub(crate) fn should_notify(&self, container_id: &ContainerID) -> bool { if !self.root_observers.is_empty() { return true; } @@ -376,7 +380,7 @@ impl Hierarchy { } } - pub fn subscribe(&mut self, observer: Observer) -> SubscriptionID { + pub(crate) fn subscribe(&mut self, observer: Observer) -> SubscriptionID { let id = self.next_id(); if observer.root() { self.root_observers.insert(id); @@ -433,7 +437,7 @@ impl Hierarchy { // Do we need return the information that the id does not exist ? // Considering if in calling, the delete operation is delayed. - pub fn unsubscribe(&mut self, id: SubscriptionID) { + pub(crate) fn unsubscribe(&mut self, id: SubscriptionID) { if self.calling { self.deleted_observers.insert(id); } else { @@ -447,7 +451,7 @@ impl Hierarchy { } } - pub fn send_notifications_without_lock( + pub(crate) fn send_notifications_without_lock( hierarchy: Arc>, events: Vec, ) { diff --git a/crates/loro-internal/src/log_store/encoding.rs b/crates/loro-internal/src/log_store/encoding.rs index 0d112341..66d70975 100644 --- a/crates/loro-internal/src/log_store/encoding.rs +++ b/crates/loro-internal/src/log_store/encoding.rs @@ -118,7 +118,7 @@ impl LoroEncoder { ans } - pub fn decode( + pub(crate) fn decode( store: &mut LogStore, hierarchy: &mut Hierarchy, input: &[u8], @@ -139,7 +139,7 @@ impl LoroEncoder { } } - pub fn decode_batch( + pub(crate) fn decode_batch( store: &mut LogStore, hierarchy: &mut Hierarchy, batch: &[Vec], diff --git a/crates/loro-internal/src/log_store/import.rs b/crates/loro-internal/src/log_store/import.rs index 2bae1b37..58046452 100644 --- a/crates/loro-internal/src/log_store/import.rs +++ b/crates/loro-internal/src/log_store/import.rs @@ -81,7 +81,7 @@ impl LogStore { /// - Update the rest of the log store state. /// #[instrument(skip_all)] - pub fn import( + pub(crate) fn import( &mut self, hierarchy: &mut Hierarchy, mut changes: RemoteClientChanges, diff --git a/crates/loro-internal/src/loro.rs b/crates/loro-internal/src/loro.rs index 7a559595..ed98fc7f 100644 --- a/crates/loro-internal/src/loro.rs +++ b/crates/loro-internal/src/loro.rs @@ -177,7 +177,7 @@ impl LoroCore { } #[instrument(skip_all)] - pub fn notify(&self, events: Vec) { + pub(crate) fn notify(&self, events: Vec) { Hierarchy::send_notifications_without_lock(self.hierarchy.clone(), events) } diff --git a/crates/loro-internal/src/transaction.rs b/crates/loro-internal/src/transaction.rs index 689ab939..639f5263 100644 --- a/crates/loro-internal/src/transaction.rs +++ b/crates/loro-internal/src/transaction.rs @@ -78,6 +78,11 @@ impl TransactionWrap { let instance = txn.with_store(|s| s.get_container_by_idx(&idx)); instance.map(|i| Map::from_instance(i, txn.client_id)) } + + pub fn decode(&mut self, input: &[u8]) -> Result<(), LoroError> { + let mut txn = self.0.borrow_mut(); + txn.decode(input) + } } // TODO: use String as Origin for now diff --git a/crates/loro/Cargo.toml b/crates/loro/Cargo.toml index 6bc83891..f8787fa3 100644 --- a/crates/loro/Cargo.toml +++ b/crates/loro/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +loro-internal = { path = "../loro-internal" } diff --git a/crates/loro/src/lib.rs b/crates/loro/src/lib.rs index 7d12d9af..a9b48818 100644 --- a/crates/loro/src/lib.rs +++ b/crates/loro/src/lib.rs @@ -1,14 +1,105 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} +use loro_internal::{ + configure::Configure, + container::ContainerIdRaw, + event::{ObserverHandler, SubscriptionID}, + LoroCore, Transact, TransactionWrap, +}; -#[cfg(test)] -mod tests { - use super::*; +pub use loro_internal::{ + container::ContainerIdx, event, id::ClientID, EncodeMode, List, LoroError, LoroValue, Map, + Text, VersionVector, +}; - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); +#[repr(transparent)] +#[derive(Default)] +pub struct Loro(LoroCore); + +impl Loro { + #[inline(always)] + pub fn new(cfg: Configure, client_id: Option) -> Self { + Self(LoroCore::new(cfg, client_id)) + } + + #[inline(always)] + pub fn client_id(&self) -> ClientID { + self.0.client_id() + } + + #[inline(always)] + pub fn vv_cloned(&self) -> VersionVector { + self.0.vv_cloned() + } + + #[inline(always)] + pub fn get_list>(&mut self, id_or_name: I) -> List { + self.0.get_list(id_or_name) + } + + #[inline(always)] + pub fn get_map>(&mut self, id_or_name: I) -> Map { + self.0.get_map(id_or_name) + } + + #[inline(always)] + pub fn get_text>(&mut self, id_or_name: I) -> Text { + self.0.get_text(id_or_name) + } + + #[inline(always)] + pub fn encode_all(&self) -> Vec { + self.0.encode_all() + } + + #[inline(always)] + pub fn encode_from(&self, from: VersionVector) -> Vec { + self.0.encode_from(from) + } + + #[inline(always)] + pub fn encode_with_cfg(&self, mode: EncodeMode) -> Vec { + self.0.encode_with_cfg(mode) + } + + #[inline(always)] + pub fn decode(&mut self, input: &[u8]) -> Result<(), LoroError> { + self.0.decode(input) + } + + #[inline(always)] + pub fn to_json(&self) -> LoroValue { + self.0.to_json() + } + + #[inline(always)] + pub fn subscribe_deep(&mut self, handler: ObserverHandler) -> SubscriptionID { + self.0.subscribe_deep(handler) + } + + #[inline(always)] + pub fn unsubscribe_deep(&mut self, subscription: SubscriptionID) { + self.0.unsubscribe_deep(subscription) + } + + #[inline(always)] + pub fn subscribe_once(&mut self, handler: ObserverHandler) -> SubscriptionID { + self.0.subscribe_once(handler) + } + + /// Execute with transaction + #[inline(always)] + pub fn txn(&mut self, f: impl FnOnce(TransactionWrap)) { + f(self.transact()) + } +} + +impl Transact for Loro { + #[inline(always)] + fn transact(&self) -> loro_internal::TransactionWrap { + self.0.transact() + } + + #[inline(always)] + fn transact_with(&self, origin: Option) -> TransactionWrap { + self.0.transact_with(origin) } } diff --git a/crates/loro/tests/test.rs b/crates/loro/tests/test.rs new file mode 100644 index 00000000..e9ceccf1 --- /dev/null +++ b/crates/loro/tests/test.rs @@ -0,0 +1,17 @@ +use loro::Loro; + +#[test] +fn input_text() { + let mut doc = Loro::new(Default::default(), None); + let mut text = doc.get_text("text"); + doc.txn(|txn| { + text.insert(&txn, 0, "123").unwrap(); + }); + let mut doc_b = Loro::new(Default::default(), None); + doc_b.txn(|mut txn| { + txn.decode(&doc.encode_all()).unwrap(); + }); + + let a = doc.to_json(); + assert_eq!(a, doc_b.to_json()); +}