mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-05 20:17:13 +00:00
chore: bk
This commit is contained in:
parent
2df7429e58
commit
abd3e38253
10 changed files with 167 additions and 13 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -25,6 +25,7 @@
|
|||
},
|
||||
"rust-analyzer.cargo.features": ["test_utils"],
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||
"rust-analyzer.server.extraEnv": { "RUSTUP_TOOLCHAIN": "stable" },
|
||||
"editor.formatOnSave": true,
|
||||
"todo-tree.general.tags": [
|
||||
"BUG",
|
||||
|
|
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -528,6 +528,18 @@ dependencies = [
|
|||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum_dispatch"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11f36e95862220b211a6e2aa5eca09b4fa391b13cd52ceb8035a24bf65a79de2"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.8.0"
|
||||
|
@ -786,6 +798,7 @@ dependencies = [
|
|||
"debug-log",
|
||||
"dhat",
|
||||
"enum-as-inner",
|
||||
"enum_dispatch",
|
||||
"flate2",
|
||||
"fxhash",
|
||||
"itertools",
|
||||
|
|
|
@ -31,6 +31,7 @@ serde_columnar = { version = "0.2.5" }
|
|||
tracing = { version = "0.1.37" }
|
||||
append-only-bytes = { version = "0.1.4", features = ["u32_range"] }
|
||||
itertools = "0.10.5"
|
||||
enum_dispatch = "0.3.11"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0.87"
|
||||
|
|
|
@ -19,6 +19,8 @@ pub type Timestamp = i64;
|
|||
pub type Lamport = u32;
|
||||
|
||||
/// A `Change` contains a list of [Op]s.
|
||||
///
|
||||
/// When undo/redo we should always undo/redo a whole [Change].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Change<O = Op> {
|
||||
pub(crate) ops: RleVec<[O; 2]>,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::sync::{Arc, Mutex, Weak};
|
||||
use std::sync::{Mutex, Weak};
|
||||
|
||||
use append_only_bytes::AppendOnlyBytes;
|
||||
use debug_log::debug_dbg;
|
||||
use rle::HasLength;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use tracing::instrument;
|
||||
|
@ -21,7 +20,6 @@ use crate::{
|
|||
op::{InnerContent, Op, RemoteContent, RichOp},
|
||||
transaction::Transaction,
|
||||
value::LoroValue,
|
||||
version::PatchedVersionVector,
|
||||
LoroError, Transact, VersionVector,
|
||||
};
|
||||
|
||||
|
@ -29,7 +27,7 @@ use super::{
|
|||
rope::Rope,
|
||||
string_pool::{Alive, PoolString, StringPool},
|
||||
text_content::{ListSlice, SliceRange},
|
||||
tracker::{Effect, Tracker},
|
||||
tracker::Tracker,
|
||||
utf16::count_utf16_chars,
|
||||
};
|
||||
|
||||
|
@ -87,6 +85,8 @@ impl TextContainer {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn diff(&mut self) {}
|
||||
|
||||
fn _record_insert_op(
|
||||
&mut self,
|
||||
txn: &mut Transaction,
|
||||
|
|
|
@ -59,7 +59,7 @@ impl GcConfig {
|
|||
}
|
||||
}
|
||||
|
||||
type ClientChanges = FxHashMap<ClientID, RleVecWithIndex<Change, ChangeMergeCfg>>;
|
||||
pub(crate) type ClientChanges = FxHashMap<ClientID, RleVecWithIndex<Change, ChangeMergeCfg>>;
|
||||
pub(crate) type RemoteClientChanges = FxHashMap<ClientID, Vec<Change<RemoteOp>>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -15,11 +15,6 @@ use smallvec::SmallVec;
|
|||
|
||||
/// Operation is a unit of change.
|
||||
///
|
||||
/// It has 3 types:
|
||||
/// - Insert
|
||||
/// - Delete
|
||||
/// - Restore
|
||||
///
|
||||
/// A Op may have multiple atomic operations, since Op can be merged.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Op {
|
||||
|
|
|
@ -1,4 +1,43 @@
|
|||
/// This store the
|
||||
pub struct OpLog {}
|
||||
mod dag;
|
||||
|
||||
pub struct Dag {}
|
||||
use fxhash::FxHashMap;
|
||||
use rle::{HasIndex, HasLength, Mergable, RleVec, Sliceable};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::change::{Change, Lamport, Timestamp};
|
||||
use crate::dag::{Dag, DagNode};
|
||||
use crate::id::{ClientID, Counter, ID};
|
||||
use crate::log_store::ClientChanges;
|
||||
use crate::span::{HasId, HasLamport};
|
||||
use crate::version::{Frontiers, VersionVector};
|
||||
|
||||
/// [OpLog] store all the ops i.e. the history.
|
||||
/// It allows multiple [AppState] to attach to it.
|
||||
/// So you can derive different versions of the state from the [OpLog].
|
||||
/// It allows us to build a version control system.
|
||||
///
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OpLog {
|
||||
pub(crate) dag: AppDag,
|
||||
pub(crate) changes: ClientChanges,
|
||||
pub(crate) latest_lamport: Lamport,
|
||||
pub(crate) latest_timestamp: Timestamp,
|
||||
}
|
||||
|
||||
/// [AppDag] maintains the causal graph of the app.
|
||||
/// It's faster to answer the question like what's the LCA version
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppDag {
|
||||
map: FxHashMap<ClientID, RleVec<[AppDagNode; 1]>>,
|
||||
frontiers: Frontiers,
|
||||
vv: VersionVector,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppDagNode {
|
||||
client: ClientID,
|
||||
cnt: Counter,
|
||||
lamport: Lamport,
|
||||
parents: SmallVec<[ID; 2]>,
|
||||
len: usize,
|
||||
}
|
||||
|
|
75
crates/loro-internal/src/refactor/oplog/dag.rs
Normal file
75
crates/loro-internal/src/refactor/oplog/dag.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use super::*;
|
||||
impl HasIndex for AppDagNode {
|
||||
type Int = Counter;
|
||||
fn get_start_index(&self) -> Self::Int {
|
||||
self.cnt
|
||||
}
|
||||
|
||||
fn get_end_index(&self) -> Self::Int {
|
||||
self.cnt + self.len as Counter
|
||||
}
|
||||
}
|
||||
|
||||
impl Sliceable for AppDagNode {
|
||||
fn slice(&self, from: usize, to: usize) -> Self {
|
||||
AppDagNode {
|
||||
client: self.client,
|
||||
cnt: self.cnt + from as Counter,
|
||||
lamport: self.lamport + from as Lamport,
|
||||
parents: Default::default(),
|
||||
len: to - from,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasId for AppDagNode {
|
||||
fn id_start(&self) -> ID {
|
||||
ID {
|
||||
client_id: self.client,
|
||||
counter: self.cnt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLength for AppDagNode {
|
||||
fn atom_len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
fn content_len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
}
|
||||
|
||||
impl Mergable for AppDagNode {}
|
||||
|
||||
impl HasLamport for AppDagNode {
|
||||
fn lamport(&self) -> Lamport {
|
||||
self.lamport
|
||||
}
|
||||
}
|
||||
|
||||
impl DagNode for AppDagNode {
|
||||
fn deps(&self) -> &[ID] {
|
||||
&self.parents
|
||||
}
|
||||
}
|
||||
|
||||
impl Dag for AppDag {
|
||||
type Node = AppDagNode;
|
||||
|
||||
fn frontier(&self) -> &[ID] {
|
||||
&self.frontiers
|
||||
}
|
||||
|
||||
fn get(&self, id: ID) -> Option<&Self::Node> {
|
||||
let ID { client_id, counter } = id;
|
||||
self.map
|
||||
.get(&client_id)
|
||||
.and_then(|rle| rle.get(counter).map(|x| x.element))
|
||||
}
|
||||
|
||||
fn vv(&self) -> VersionVector {
|
||||
self.vv.clone()
|
||||
}
|
||||
}
|
|
@ -1,7 +1,35 @@
|
|||
use enum_dispatch::enum_dispatch;
|
||||
use fxhash::FxHashMap;
|
||||
|
||||
use crate::{container::ContainerID, InternalString, VersionVector};
|
||||
|
||||
mod list;
|
||||
mod map;
|
||||
mod text;
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait ContainerState: Clone {
|
||||
fn apply_diff(&mut self);
|
||||
}
|
||||
|
||||
pub struct AppState {
|
||||
vv: VersionVector,
|
||||
state: FxHashMap<ContainerID, State>,
|
||||
}
|
||||
|
||||
#[enum_dispatch(ContainerState)]
|
||||
#[derive(Clone)]
|
||||
pub enum State {
|
||||
ListState,
|
||||
MapState,
|
||||
TextState,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ListState {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MapState {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TextState {}
|
||||
|
|
Loading…
Reference in a new issue