refactor: rename stable pos to cursor (#317)

This commit is contained in:
Zixuan Chen 2024-04-10 12:26:12 +08:00 committed by GitHub
parent 454b4088a6
commit 1918cd7ac3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 59 additions and 54 deletions

View file

@ -5,7 +5,7 @@ use generic_btree::{
use loro_common::{Counter, HasId, HasIdSpan, IdFull, IdSpan, Lamport, PeerID, ID};
use rle::HasLength;
use crate::{stable_pos::AbsolutePosition, VersionVector};
use crate::{cursor::AbsolutePosition, VersionVector};
use self::{crdt_rope::CrdtRope, id_to_cursor::IdToCursor};
@ -386,9 +386,9 @@ impl Tracker {
return Some(AbsolutePosition {
pos: index,
side: if is_activated {
crate::stable_pos::Side::Middle
crate::cursor::Side::Middle
} else {
crate::stable_pos::Side::Left
crate::cursor::Side::Left
},
});
}

View file

@ -18,11 +18,11 @@ use crate::{
AnchorType, CrdtRopeDelta, RichtextChunk, RichtextChunkValue, RichtextTracker, StyleOp,
},
},
cursor::AbsolutePosition,
delta::{Delta, MapDelta, MapValue},
event::InternalDiff,
op::{RichOp, SliceRange, SliceRanges},
span::{HasId, HasLamport},
stable_pos::AbsolutePosition,
version::Frontiers,
InternalString, VersionVector,
};
@ -462,7 +462,7 @@ pub(crate) struct ListDiffCalculator {
tracker: Box<RichtextTracker>,
}
impl ListDiffCalculator {
pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option<crate::stable_pos::AbsolutePosition> {
pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option<crate::cursor::AbsolutePosition> {
self.tracker.get_target_id_latest_index_at_new_version(id)
}
}

View file

@ -7,9 +7,9 @@ use crate::{
richtext::{richtext_state::PosType, RichtextState, StyleOp, TextStyleInfoFlag},
tree::tree_op::TreeOp,
},
cursor::{Cursor, Side},
delta::{DeltaItem, StyleMeta, TreeDiffItem, TreeExternalDiff},
op::ListSlice,
stable_pos::{Cursor, Side},
state::{ContainerState, State, TreeParentId},
txn::EventHint,
utils::{string_slice::StringSlice, utf16::count_utf16_len},

View file

@ -15,10 +15,10 @@ pub use handler::{BasicHandler, HandlerTrait, ListHandler, MapHandler, TextHandl
pub use loro::LoroDoc;
pub use oplog::OpLog;
pub use state::DocState;
pub mod cursor;
pub mod loro;
pub mod obs;
pub mod oplog;
pub mod stable_pos;
pub mod txn;
pub mod change;

View file

@ -21,6 +21,7 @@ use crate::{
idx::ContainerIdx, list::list_op::InnerListOp, richtext::config::StyleConfigMap,
IntoContainerId,
},
cursor::{AbsolutePosition, CannotFindRelativePosition, Cursor, PosQueryResult},
dag::DagUtils,
encoding::{
decode_snapshot, export_snapshot, parse_header_and_body, EncodeMode, ParsedHeaderAndBody,
@ -30,7 +31,6 @@ use crate::{
id::PeerID,
op::InnerContent,
oplog::dag::FrontiersNotIncluded,
stable_pos::{AbsolutePosition, CannotFindRelativePosition, Cursor, PosQueryResult},
version::Frontiers,
HandlerTrait, InternalString, LoroError, VersionVector,
};

View file

@ -14,6 +14,7 @@ use crate::{
idx::ContainerIdx, list::list_op::ListOp, map::MapSet, richtext::config::StyleConfigMap,
tree::tree_op::TreeOp, ContainerIdRaw,
},
cursor::Cursor,
delta::DeltaItem,
encoding::{StateSnapshotDecodeContext, StateSnapshotEncoder},
event::{Diff, EventTriggerKind, Index, InternalContainerDiff, InternalDiff},
@ -21,7 +22,6 @@ use crate::{
handler::ValueOrHandler,
id::PeerID,
op::{ListSlice, Op, RawOp, RawOpContent},
stable_pos::Cursor,
txn::Transaction,
version::Frontiers,
ContainerDiff, ContainerType, DocDiff, InternalString, LoroValue,
@ -1095,7 +1095,7 @@ impl DocState {
}
}
} else {
if matches!(pos.side, crate::stable_pos::Side::Left) {
if matches!(pos.side, crate::cursor::Side::Left) {
return Some(0);
}

View file

@ -5,6 +5,7 @@ use loro_internal::{
change::Lamport,
configure::{StyleConfig, StyleConfigMap},
container::{richtext::ExpandType, ContainerID},
cursor::{self, Side},
encoding::ImportBlobMetadata,
event::Index,
handler::{
@ -12,7 +13,6 @@ use loro_internal::{
},
id::{Counter, TreeID, ID},
obs::SubID,
stable_pos::{self, Side},
version::Frontiers,
ContainerType, DiffEvent, HandlerTrait, LoroDoc, LoroValue,
VersionVector as InternalVersionVector,
@ -136,8 +136,8 @@ extern "C" {
pub type JsImportBlobMetadata;
#[wasm_bindgen(typescript_type = "Side")]
pub type JsSide;
#[wasm_bindgen(typescript_type = "{ update?: StablePosition, offset: number, side: Side }")]
pub type JsStablePosQueryAns;
#[wasm_bindgen(typescript_type = "{ update?: Cursor, offset: number, side: Side }")]
pub type JsCursorQueryAns;
}
mod observer {
@ -1135,14 +1135,14 @@ impl Loro {
/// expect(ans.offset).toBe(1);
/// }
/// ```
pub fn getCursorPos(&self, stable_pos: &StablePosition) -> JsResult<JsStablePosQueryAns> {
pub fn getCursorPos(&self, cursor: &Cursor) -> JsResult<JsCursorQueryAns> {
let ans = self
.0
.query_pos(&stable_pos.pos)
.query_pos(&cursor.pos)
.map_err(|e| JsError::new(&e.to_string()))?;
let obj = Object::new();
let update = ans.update.map(|u| StablePosition { pos: u });
let update = ans.update.map(|u| Cursor { pos: u });
if let Some(update) = update {
let update_value: JsValue = update.into();
Reflect::set(&obj, &JsValue::from_str("update"), &update_value)?;
@ -1505,7 +1505,7 @@ impl LoroText {
}
#[wasm_bindgen(skip_typescript)]
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<StablePosition> {
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<Cursor> {
let mut side_value = Side::Middle;
if side.is_truthy() {
let num = side.as_f64().expect("Side must be -1 | 0 | 1");
@ -1513,7 +1513,7 @@ impl LoroText {
}
self.handler
.get_cursor(pos, side_value)
.map(|pos| StablePosition { pos })
.map(|pos| Cursor { pos })
}
}
@ -2131,7 +2131,7 @@ impl LoroList {
}
#[wasm_bindgen(skip_typescript)]
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<StablePosition> {
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<Cursor> {
let mut side_value = Side::Middle;
if side.is_truthy() {
let num = side.as_f64().expect("Side must be -1 | 0 | 1");
@ -2139,7 +2139,7 @@ impl LoroList {
}
self.handler
.get_cursor(pos, side_value)
.map(|pos| StablePosition { pos })
.map(|pos| Cursor { pos })
}
}
@ -2569,12 +2569,12 @@ impl Default for LoroTree {
#[derive(Clone)]
#[wasm_bindgen]
pub struct StablePosition {
pos: stable_pos::Cursor,
pub struct Cursor {
pos: cursor::Cursor,
}
#[wasm_bindgen]
impl StablePosition {
impl Cursor {
pub fn containerId(&self) -> JsContainerID {
let js_value: JsValue = self.pos.container.to_string().into();
JsContainerID::from(js_value)
@ -2592,9 +2592,9 @@ impl StablePosition {
pub fn side(&self) -> JsSide {
JsValue::from(match self.pos.side {
stable_pos::Side::Left => -1,
stable_pos::Side::Middle => 0,
stable_pos::Side::Right => 1,
cursor::Side::Left => -1,
cursor::Side::Middle => 0,
cursor::Side::Right => 1,
})
.into()
}
@ -2603,10 +2603,9 @@ impl StablePosition {
self.pos.encode()
}
pub fn decode(data: &[u8]) -> JsResult<StablePosition> {
let pos =
stable_pos::Cursor::decode(data).map_err(|e| JsValue::from_str(&e.to_string()))?;
Ok(StablePosition { pos })
pub fn decode(data: &[u8]) -> JsResult<Cursor> {
let pos = cursor::Cursor::decode(data).map_err(|e| JsValue::from_str(&e.to_string()))?;
Ok(Cursor { pos })
}
}
@ -2940,19 +2939,19 @@ export interface ImportBlobMetadata {
interface LoroText {
/**
* Get a stable position representing the cursor position.
* Get the cursor position at the given pos.
*
* When expressing the position of a cursor, using "index" can be unstable
* because the cursor's position may change due to other deletions and insertions,
* requiring updates with each edit. To stably represent a position or range within
* a list structure, we can utilize the ID of each item/character on List CRDT or
* Text CRDT for expression.
*
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
* approach complicates tracking cursors since they rely on these IDs. The solution
* recalculates position by replaying relevant history to update stable positions
* accurately. To minimize the performance impact of history replay, the system
* updates cursor info to reference only the IDs of currently present elements,
*
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
* approach complicates tracking cursors since they rely on these IDs. The solution
* recalculates position by replaying relevant history to update cursors
* accurately. To minimize the performance impact of history replay, the system
* updates cursor info to reference only the IDs of currently present elements,
* thereby reducing the need for replay.
*
* @example
@ -2973,24 +2972,24 @@ interface LoroText {
* }
* ```
*/
getCursor(pos: number, side?: Side): StablePosition | undefined;
getCursor(pos: number, side?: Side): Cursor | undefined;
}
interface LoroList {
/**
* Get a stable position representing the cursor position.
* Get the cursor position at the given pos.
*
* When expressing the position of a cursor, using "index" can be unstable
* because the cursor's position may change due to other deletions and insertions,
* requiring updates with each edit. To stably represent a position or range within
* a list structure, we can utilize the ID of each item/character on List CRDT or
* Text CRDT for expression.
*
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
* approach complicates tracking cursors since they rely on these IDs. The solution
* recalculates position by replaying relevant history to update stable positions
* accurately. To minimize the performance impact of history replay, the system
* updates cursor info to reference only the IDs of currently present elements,
*
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
* approach complicates tracking cursors since they rely on these IDs. The solution
* recalculates position by replaying relevant history to update cursors
* accurately. To minimize the performance impact of history replay, the system
* updates cursor info to reference only the IDs of currently present elements,
* thereby reducing the need for replay.
*
* @example
@ -3011,7 +3010,7 @@ interface LoroList {
* }
* ```
*/
getCursor(pos: number, side?: Side): StablePosition | undefined;
getCursor(pos: number, side?: Side): Cursor | undefined;
}
export type Side = -1 | 0 | 1;

View file

@ -3,13 +3,13 @@ use either::Either;
use event::{DiffEvent, Subscriber};
use loro_internal::change::Timestamp;
use loro_internal::container::IntoContainerId;
use loro_internal::cursor::CannotFindRelativePosition;
use loro_internal::cursor::Cursor;
use loro_internal::cursor::PosQueryResult;
use loro_internal::cursor::Side;
use loro_internal::encoding::ImportBlobMetadata;
use loro_internal::handler::HandlerTrait;
use loro_internal::handler::ValueOrHandler;
use loro_internal::stable_pos::CannotFindRelativePosition;
use loro_internal::stable_pos::Cursor;
use loro_internal::stable_pos::PosQueryResult;
use loro_internal::stable_pos::Side;
use loro_internal::LoroDoc as InnerLoroDoc;
use loro_internal::OpLog;
@ -596,7 +596,7 @@ impl LoroList {
///
/// ```
/// use loro::LoroDoc;
/// use loro_internal::stable_pos::Side;
/// use loro_internal::cursor::Side;
///
/// let doc = LoroDoc::new();
/// let list = doc.get_list("list");

View file

@ -49,7 +49,7 @@ fn readme_basic() {
#[test]
fn get_list_cursor_example() {
use loro::LoroDoc;
use loro_internal::stable_pos::Side;
use loro_internal::cursor::Side;
let doc = LoroDoc::new();
let list = doc.get_list("list");

View file

@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { Delta, Loro, TextDiff } from "../src";
import { OpId, setDebug } from "loro-wasm";
import { Cursor, OpId, setDebug } from "loro-wasm";
describe("richtext", () => {
it("mark", () => {
@ -237,12 +237,18 @@ describe("richtext", () => {
expect(ans.update).toBeUndefined();
}
text.insert(0, "abc");
const bytes = pos0!.encode();
// Sending pos0 over the network
const pos0decoded = Cursor.decode(bytes);
const docA = new Loro();
docA.import(doc.exportFrom());
{
const ans = doc.getCursorPos(pos0!);
const ans = docA.getCursorPos(pos0decoded!);
expect(ans.side).toBe(0);
expect(ans.offset).toBe(3);
expect(ans.update).toBeUndefined();
}
// If "1" is removed from the text, the stable position should be updated
text.delete(3, 1); // remove "1", "abc23"
doc.commit();