document_pad.rs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. use crate::{
  2. client_document::{
  3. history::{History, UndoResult},
  4. view::{ViewExtensions, RECORD_THRESHOLD},
  5. },
  6. errors::SyncError,
  7. };
  8. use bytes::Bytes;
  9. use lib_infra::util::md5;
  10. use lib_ot::text_delta::DeltaTextOperationBuilder;
  11. use lib_ot::{core::*, text_delta::DeltaTextOperations};
  12. use tokio::sync::mpsc;
  13. pub trait InitialDocument {
  14. fn json_str() -> String;
  15. }
  16. pub struct EmptyDocument();
  17. impl InitialDocument for EmptyDocument {
  18. fn json_str() -> String {
  19. DeltaTextOperations::default().json_str()
  20. }
  21. }
  22. pub struct NewlineDocument();
  23. impl InitialDocument for NewlineDocument {
  24. fn json_str() -> String {
  25. initial_delta_document_content()
  26. }
  27. }
  28. pub fn initial_delta_document_content() -> String {
  29. DeltaTextOperationBuilder::new().insert("\n").build().json_str()
  30. }
  31. pub struct ClientDocument {
  32. operations: DeltaTextOperations,
  33. history: History,
  34. view: ViewExtensions,
  35. last_edit_time: usize,
  36. notify: Option<mpsc::UnboundedSender<()>>,
  37. }
  38. impl ClientDocument {
  39. pub fn new<C: InitialDocument>() -> Self {
  40. let content = C::json_str();
  41. Self::from_json(&content).unwrap()
  42. }
  43. pub fn from_operations(operations: DeltaTextOperations) -> Self {
  44. ClientDocument {
  45. operations,
  46. history: History::new(),
  47. view: ViewExtensions::new(),
  48. last_edit_time: 0,
  49. notify: None,
  50. }
  51. }
  52. pub fn from_json(json: &str) -> Result<Self, SyncError> {
  53. let operations = DeltaTextOperations::from_json(json)?;
  54. Ok(Self::from_operations(operations))
  55. }
  56. pub fn get_operations_json(&self) -> String {
  57. self.operations.json_str()
  58. }
  59. pub fn to_bytes(&self) -> Bytes {
  60. self.operations.json_bytes()
  61. }
  62. pub fn to_content(&self) -> String {
  63. self.operations.content().unwrap()
  64. }
  65. pub fn get_operations(&self) -> &DeltaTextOperations {
  66. &self.operations
  67. }
  68. pub fn document_md5(&self) -> String {
  69. let bytes = self.to_bytes();
  70. md5(&bytes)
  71. }
  72. pub fn set_notify(&mut self, notify: mpsc::UnboundedSender<()>) {
  73. self.notify = Some(notify);
  74. }
  75. pub fn set_operations(&mut self, operations: DeltaTextOperations) {
  76. tracing::trace!("document: {}", operations.json_str());
  77. self.operations = operations;
  78. match &self.notify {
  79. None => {}
  80. Some(notify) => {
  81. let _ = notify.send(());
  82. }
  83. }
  84. }
  85. pub fn compose_operations(&mut self, operations: DeltaTextOperations) -> Result<(), SyncError> {
  86. tracing::trace!("{} compose {}", &self.operations.json_str(), operations.json_str());
  87. let composed_operations = self.operations.compose(&operations)?;
  88. let mut undo_operations = operations.invert(&self.operations);
  89. let now = chrono::Utc::now().timestamp_millis() as usize;
  90. if now - self.last_edit_time < RECORD_THRESHOLD {
  91. if let Some(last_operation) = self.history.undo() {
  92. tracing::trace!("compose previous change");
  93. tracing::trace!("current = {}", undo_operations);
  94. tracing::trace!("previous = {}", last_operation);
  95. undo_operations = undo_operations.compose(&last_operation)?;
  96. }
  97. } else {
  98. self.last_edit_time = now;
  99. }
  100. if !undo_operations.is_empty() {
  101. tracing::trace!("add history operations: {}", undo_operations);
  102. self.history.record(undo_operations);
  103. }
  104. self.set_operations(composed_operations);
  105. Ok(())
  106. }
  107. pub fn insert<T: ToString>(&mut self, index: usize, data: T) -> Result<DeltaTextOperations, SyncError> {
  108. let text = data.to_string();
  109. let interval = Interval::new(index, index);
  110. validate_interval(&self.operations, &interval)?;
  111. let operations = self.view.insert(&self.operations, &text, interval)?;
  112. self.compose_operations(operations.clone())?;
  113. Ok(operations)
  114. }
  115. pub fn delete(&mut self, interval: Interval) -> Result<DeltaTextOperations, SyncError> {
  116. validate_interval(&self.operations, &interval)?;
  117. debug_assert!(!interval.is_empty());
  118. let operations = self.view.delete(&self.operations, interval)?;
  119. if !operations.is_empty() {
  120. self.compose_operations(operations.clone())?;
  121. }
  122. Ok(operations)
  123. }
  124. pub fn format(&mut self, interval: Interval, attribute: AttributeEntry) -> Result<DeltaTextOperations, SyncError> {
  125. validate_interval(&self.operations, &interval)?;
  126. tracing::trace!("format {} with {:?}", interval, attribute);
  127. let operations = self.view.format(&self.operations, attribute, interval).unwrap();
  128. self.compose_operations(operations.clone())?;
  129. Ok(operations)
  130. }
  131. pub fn replace<T: ToString>(&mut self, interval: Interval, data: T) -> Result<DeltaTextOperations, SyncError> {
  132. validate_interval(&self.operations, &interval)?;
  133. let mut operations = DeltaTextOperations::default();
  134. let text = data.to_string();
  135. if !text.is_empty() {
  136. operations = self.view.insert(&self.operations, &text, interval)?;
  137. self.compose_operations(operations.clone())?;
  138. }
  139. if !interval.is_empty() {
  140. let delete = self.delete(interval)?;
  141. operations = operations.compose(&delete)?;
  142. }
  143. Ok(operations)
  144. }
  145. pub fn can_undo(&self) -> bool {
  146. self.history.can_undo()
  147. }
  148. pub fn can_redo(&self) -> bool {
  149. self.history.can_redo()
  150. }
  151. pub fn undo(&mut self) -> Result<UndoResult, SyncError> {
  152. match self.history.undo() {
  153. None => Err(SyncError::undo().context("Undo stack is empty")),
  154. Some(undo_operations) => {
  155. let (new_operations, inverted_operations) = self.invert(&undo_operations)?;
  156. self.set_operations(new_operations);
  157. self.history.add_redo(inverted_operations);
  158. Ok(UndoResult {
  159. operations: undo_operations,
  160. })
  161. }
  162. }
  163. }
  164. pub fn redo(&mut self) -> Result<UndoResult, SyncError> {
  165. match self.history.redo() {
  166. None => Err(SyncError::redo()),
  167. Some(redo_operations) => {
  168. let (new_operations, inverted_operations) = self.invert(&redo_operations)?;
  169. self.set_operations(new_operations);
  170. self.history.add_undo(inverted_operations);
  171. Ok(UndoResult {
  172. operations: redo_operations,
  173. })
  174. }
  175. }
  176. }
  177. pub fn is_empty(&self) -> bool {
  178. // The document is empty if its text is equal to the initial text.
  179. self.operations.json_str() == NewlineDocument::json_str()
  180. }
  181. }
  182. impl ClientDocument {
  183. fn invert(
  184. &self,
  185. operations: &DeltaTextOperations,
  186. ) -> Result<(DeltaTextOperations, DeltaTextOperations), SyncError> {
  187. // c = a.compose(b)
  188. // d = b.invert(a)
  189. // a = c.compose(d)
  190. let new_operations = self.operations.compose(operations)?;
  191. let inverted_operations = operations.invert(&self.operations);
  192. Ok((new_operations, inverted_operations))
  193. }
  194. }
  195. fn validate_interval(operations: &DeltaTextOperations, interval: &Interval) -> Result<(), SyncError> {
  196. if operations.utf16_target_len < interval.end {
  197. tracing::error!(
  198. "{:?} out of bounds. should 0..{}",
  199. interval,
  200. operations.utf16_target_len
  201. );
  202. return Err(SyncError::out_of_bound());
  203. }
  204. Ok(())
  205. }