2022-01-02 14:23:33 +00:00
|
|
|
use crate::{
|
2022-01-03 04:20:06 +00:00
|
|
|
entities::revision::{RepeatedRevision, Revision},
|
2022-01-02 14:23:33 +00:00
|
|
|
errors::{CollaborateError, CollaborateResult},
|
2022-01-03 04:20:06 +00:00
|
|
|
protobuf::{RepeatedRevision as RepeatedRevisionPB, Revision as RevisionPB},
|
2022-01-02 14:23:33 +00:00
|
|
|
};
|
|
|
|
use lib_ot::{
|
|
|
|
core::{OperationTransformable, NEW_LINE, WHITESPACE},
|
|
|
|
rich_text::RichTextDelta,
|
|
|
|
};
|
2022-01-03 04:20:06 +00:00
|
|
|
use std::{
|
|
|
|
convert::TryInto,
|
|
|
|
sync::atomic::{AtomicI64, Ordering::SeqCst},
|
|
|
|
};
|
2021-09-25 13:47:02 +00:00
|
|
|
|
|
|
|
#[inline]
|
2021-11-27 11:19:41 +00:00
|
|
|
pub fn find_newline(s: &str) -> Option<usize> { s.find(NEW_LINE) }
|
2021-09-25 13:47:02 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn is_newline(s: &str) -> bool { s == NEW_LINE }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn is_whitespace(s: &str) -> bool { s == WHITESPACE }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn contain_newline(s: &str) -> bool { s.contains(NEW_LINE) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn md5<T: AsRef<[u8]>>(data: T) -> String {
|
|
|
|
let md5 = format!("{:x}", md5::compute(data));
|
|
|
|
md5
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2021-11-13 03:11:24 +00:00
|
|
|
pub struct RevIdCounter(pub AtomicI64);
|
2021-09-25 13:47:02 +00:00
|
|
|
|
|
|
|
impl RevIdCounter {
|
|
|
|
pub fn new(n: i64) -> Self { Self(AtomicI64::new(n)) }
|
|
|
|
pub fn next(&self) -> i64 {
|
|
|
|
let _ = self.0.fetch_add(1, SeqCst);
|
|
|
|
self.value()
|
|
|
|
}
|
|
|
|
pub fn value(&self) -> i64 { self.0.load(SeqCst) }
|
2021-10-04 09:38:56 +00:00
|
|
|
|
|
|
|
pub fn set(&self, n: i64) { let _ = self.0.fetch_update(SeqCst, SeqCst, |_| Some(n)); }
|
2021-09-25 13:47:02 +00:00
|
|
|
}
|
2022-01-02 14:23:33 +00:00
|
|
|
|
|
|
|
pub fn make_delta_from_revisions(revisions: Vec<Revision>) -> CollaborateResult<RichTextDelta> {
|
2022-01-06 04:39:32 +00:00
|
|
|
let mut delta = RichTextDelta::new();
|
2022-01-02 14:23:33 +00:00
|
|
|
for revision in revisions {
|
2022-01-06 04:39:32 +00:00
|
|
|
let revision_delta = RichTextDelta::from_bytes(revision.delta_data).map_err(|e| {
|
2022-01-02 14:23:33 +00:00
|
|
|
let err_msg = format!("Deserialize remote revision failed: {:?}", e);
|
|
|
|
CollaborateError::internal().context(err_msg)
|
|
|
|
})?;
|
2022-01-06 04:39:32 +00:00
|
|
|
delta = delta.compose(&revision_delta)?;
|
2022-01-02 14:23:33 +00:00
|
|
|
}
|
2022-01-06 04:39:32 +00:00
|
|
|
Ok(delta)
|
2022-01-02 14:23:33 +00:00
|
|
|
}
|
2022-01-03 04:20:06 +00:00
|
|
|
|
|
|
|
pub fn make_delta_from_revision_pb(revisions: Vec<RevisionPB>) -> CollaborateResult<RichTextDelta> {
|
|
|
|
let mut new_delta = RichTextDelta::new();
|
|
|
|
for revision in revisions {
|
|
|
|
let delta = RichTextDelta::from_bytes(revision.delta_data).map_err(|e| {
|
|
|
|
let err_msg = format!("Deserialize remote revision failed: {:?}", e);
|
|
|
|
CollaborateError::internal().context(err_msg)
|
|
|
|
})?;
|
|
|
|
new_delta = new_delta.compose(&delta)?;
|
|
|
|
}
|
|
|
|
Ok(new_delta)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn repeated_revision_from_revision_pbs(revisions: Vec<RevisionPB>) -> CollaborateResult<RepeatedRevision> {
|
|
|
|
let repeated_revision_pb = repeated_revision_pb_from_revisions(revisions);
|
|
|
|
repeated_revision_from_repeated_revision_pb(repeated_revision_pb)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn repeated_revision_pb_from_revisions(revisions: Vec<RevisionPB>) -> RepeatedRevisionPB {
|
|
|
|
let mut repeated_revision_pb = RepeatedRevisionPB::new();
|
|
|
|
repeated_revision_pb.set_items(revisions.into());
|
|
|
|
repeated_revision_pb
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn repeated_revision_from_repeated_revision_pb(
|
|
|
|
mut repeated_revision: RepeatedRevisionPB,
|
|
|
|
) -> CollaborateResult<RepeatedRevision> {
|
|
|
|
(&mut repeated_revision)
|
|
|
|
.try_into()
|
|
|
|
.map_err(|e| CollaborateError::internal().context(format!("Cast repeated revision failed: {:?}", e)))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pair_rev_id_from_revision_pbs(revisions: &[RevisionPB]) -> (i64, i64) {
|
|
|
|
let mut rev_id = 0;
|
|
|
|
revisions.iter().for_each(|revision| {
|
|
|
|
if rev_id < revision.rev_id {
|
|
|
|
rev_id = revision.rev_id;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if rev_id > 0 {
|
|
|
|
(rev_id - 1, rev_id)
|
|
|
|
} else {
|
|
|
|
(0, rev_id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pair_rev_id_from_revisions(revisions: &[Revision]) -> (i64, i64) {
|
|
|
|
let mut rev_id = 0;
|
|
|
|
revisions.iter().for_each(|revision| {
|
|
|
|
if rev_id < revision.rev_id {
|
|
|
|
rev_id = revision.rev_id;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if rev_id > 0 {
|
|
|
|
(rev_id - 1, rev_id)
|
|
|
|
} else {
|
|
|
|
(0, rev_id)
|
|
|
|
}
|
|
|
|
}
|