diff --git a/backend/reconcile/src/cursor.rs b/backend/reconcile/src/cursor.rs new file mode 100644 index 00000000..7ec9402c --- /dev/null +++ b/backend/reconcile/src/cursor.rs @@ -0,0 +1,45 @@ +use std::borrow::Cow; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +// CursorPosition is a wrapper around usize to represent the position of an +// identifiable cursor in a text document based on the character index. +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Debug, Clone, PartialEq, Default)] +pub struct CursorPosition { + pub id: usize, + pub char_index: usize, +} + +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Debug, Clone, PartialEq, Default)] +pub struct TextWithCursors<'a> { + pub text: Cow<'a, str>, + pub cursors: Vec, +} + +impl<'a> TextWithCursors<'a> { + pub fn new(text: &'a str, cursors: Vec) -> Self { + Self { + text: text.into(), + cursors, + } + } + + pub fn new_owned(text: String, cursors: Vec) -> Self { + Self { + text: text.into(), + cursors, + } + } +} + +impl<'a> From<&'a str> for TextWithCursors<'a> { + fn from(text: &'a str) -> Self { + Self { + text: text.into(), + cursors: Vec::new(), + } + } +} diff --git a/backend/sync_lib/src/cursor.rs b/backend/sync_lib/src/cursor.rs new file mode 100644 index 00000000..4b5b9a6d --- /dev/null +++ b/backend/sync_lib/src/cursor.rs @@ -0,0 +1,71 @@ +use reconcile::{CursorPosition, TextWithCursors}; +use wasm_bindgen::prelude::*; + +/// Wrapper type to expose `TextWithCursors` to JS. +#[wasm_bindgen] +#[derive(Debug, Clone, PartialEq)] +pub struct OwnedTextWithCursors { + text: String, + cursors: Vec, +} + +impl OwnedTextWithCursors { + pub fn new(text: impl Into, cursors: Vec) -> Self { + Self { + text: text.into(), + cursors, + } + } +} + +impl From for TextWithCursors<'_> { + fn from(owned: OwnedTextWithCursors) -> Self { + TextWithCursors::new_owned( + owned.text.to_string(), + owned + .cursors + .into_iter() + .map(|cursor| cursor.into()) + .collect(), + ) + } +} + +impl From> for OwnedTextWithCursors { + fn from(text_with_cursors: TextWithCursors<'_>) -> Self { + OwnedTextWithCursors { + text: text_with_cursors.text.into_owned(), + cursors: text_with_cursors + .cursors + .into_iter() + .map(|cursor| cursor.into()) + .collect(), + } + } +} + +/// Wrapper type to expose `CursorPosition` to JS. +#[wasm_bindgen] +#[derive(Debug, Clone, PartialEq)] +pub struct OwnedCursorPosition { + pub id: usize, + pub char_index: usize, +} + +impl From for CursorPosition { + fn from(owned: OwnedCursorPosition) -> Self { + CursorPosition { + id: owned.id, + char_index: owned.char_index, + } + } +} + +impl From for OwnedCursorPosition { + fn from(cursor: CursorPosition) -> Self { + OwnedCursorPosition { + id: cursor.id, + char_index: cursor.char_index, + } + } +}