loro_internal/
cursor.rs

1use loro_common::{ContainerID, ID};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
5pub struct Cursor {
6    // It's option because it's possible that the given container is empty.
7    pub id: Option<ID>,
8    pub container: ContainerID,
9    /// The target position is at the left, middle, or right of the given id.
10    ///
11    /// Side info can help to model the selection
12    pub side: Side,
13    /// The position of the cursor in the container when the cursor is created.
14    /// For text, this is the unicode codepoint index
15    /// This value is not encoded
16    pub(crate) origin_pos: usize,
17}
18
19#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
20pub enum Side {
21    Left = -1,
22    #[default]
23    Middle = 0,
24    Right = 1,
25}
26
27impl Side {
28    pub fn from_i32(i: i32) -> Option<Self> {
29        match i {
30            -1 => Some(Side::Left),
31            0 => Some(Side::Middle),
32            1 => Some(Side::Right),
33            _ => None,
34        }
35    }
36
37    pub fn to_i32(&self) -> i32 {
38        *self as i32
39    }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct PosQueryResult {
44    pub update: Option<Cursor>,
45    pub current: AbsolutePosition,
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub struct AbsolutePosition {
50    pub pos: usize,
51    /// The target position is at the left, middle, or right of the given pos.
52    pub side: Side,
53}
54
55#[derive(Debug, Clone, Copy, thiserror::Error)]
56pub enum CannotFindRelativePosition {
57    #[error("Cannot find relative position. The container is deleted.")]
58    ContainerDeleted,
59    #[error("Cannot find relative position. It may be that the given id is deleted and the relative history is cleared.")]
60    HistoryCleared,
61    #[error("Cannot find relative position. The id is not found.")]
62    IdNotFound,
63}
64
65impl Cursor {
66    pub fn new(id: Option<ID>, container: ContainerID, side: Side, origin_pos: usize) -> Self {
67        Self {
68            id,
69            container,
70            side,
71            origin_pos,
72        }
73    }
74
75    pub fn encode(&self) -> Vec<u8> {
76        postcard::to_allocvec(self).unwrap()
77    }
78
79    pub fn decode(data: &[u8]) -> Result<Self, postcard::Error> {
80        postcard::from_bytes(data)
81    }
82}