use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use lib_ot::rich_text::RichTextDelta; use std::{convert::TryFrom, fmt::Formatter, ops::RangeInclusive}; #[derive(PartialEq, Eq, Clone, Default, ProtoBuf)] pub struct Revision { #[pb(index = 1)] pub base_rev_id: i64, #[pb(index = 2)] pub rev_id: i64, #[pb(index = 3)] pub delta_data: Vec, #[pb(index = 4)] pub md5: String, #[pb(index = 5)] pub object_id: String, #[pb(index = 6)] ty: RevType, // Deprecated #[pb(index = 7)] pub user_id: String, } impl std::convert::From> for Revision { fn from(data: Vec) -> Self { let bytes = Bytes::from(data); Revision::try_from(bytes).unwrap() } } impl Revision { pub fn is_empty(&self) -> bool { self.base_rev_id == self.rev_id } pub fn pair_rev_id(&self) -> (i64, i64) { (self.base_rev_id, self.rev_id) } pub fn is_initial(&self) -> bool { self.rev_id == 0 } pub fn initial_revision(user_id: &str, object_id: &str, delta_data: Bytes) -> Self { let md5 = md5(&delta_data); Self::new(object_id, 0, 0, delta_data, user_id, md5) } pub fn new( object_id: &str, base_rev_id: i64, rev_id: i64, delta_data: Bytes, user_id: &str, md5: String, ) -> Revision { let user_id = user_id.to_owned(); let object_id = object_id.to_owned(); let delta_data = delta_data.to_vec(); let base_rev_id = base_rev_id; let rev_id = rev_id; if base_rev_id != 0 { debug_assert!(base_rev_id != rev_id); } Self { base_rev_id, rev_id, delta_data, md5, object_id, ty: RevType::DeprecatedLocal, user_id, } } } impl std::fmt::Debug for Revision { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { let _ = f.write_fmt(format_args!("object_id {}, ", self.object_id))?; let _ = f.write_fmt(format_args!("base_rev_id {}, ", self.base_rev_id))?; let _ = f.write_fmt(format_args!("rev_id {}, ", self.rev_id))?; match RichTextDelta::from_bytes(&self.delta_data) { Ok(delta) => { let _ = f.write_fmt(format_args!("delta {:?}", delta.json_str()))?; } Err(e) => { let _ = f.write_fmt(format_args!("delta {:?}", e))?; } } Ok(()) } } #[derive(PartialEq, Debug, Default, ProtoBuf, Clone)] pub struct RepeatedRevision { #[pb(index = 1)] items: Vec, } impl std::ops::Deref for RepeatedRevision { type Target = Vec; fn deref(&self) -> &Self::Target { &self.items } } impl std::ops::DerefMut for RepeatedRevision { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.items } } impl std::convert::From for RepeatedRevision { fn from(revision: Revision) -> Self { Self { items: vec![revision] } } } impl std::convert::From> for RepeatedRevision { fn from(revisions: Vec) -> Self { Self { items: revisions } } } impl RepeatedRevision { pub fn new(mut items: Vec) -> Self { items.sort_by(|a, b| a.rev_id.cmp(&b.rev_id)); Self { items } } pub fn empty() -> Self { RepeatedRevision { items: vec![] } } pub fn into_inner(self) -> Vec { self.items } } #[derive(Clone, Debug, ProtoBuf, Default)] pub struct RevId { #[pb(index = 1)] pub value: i64, } impl AsRef for RevId { fn as_ref(&self) -> &i64 { &self.value } } impl std::convert::From for i64 { fn from(rev_id: RevId) -> Self { rev_id.value } } impl std::convert::From for RevId { fn from(value: i64) -> Self { RevId { value } } } impl std::fmt::Display for RevId { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("{}", self.value)) } } #[derive(Debug, Clone, Default, ProtoBuf)] pub struct RevisionRange { #[pb(index = 1)] pub start: i64, #[pb(index = 2)] pub end: i64, } impl std::fmt::Display for RevisionRange { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("[{},{}]", self.start, self.end)) } } impl RevisionRange { pub fn len(&self) -> i64 { debug_assert!(self.end >= self.start); if self.end >= self.start { self.end - self.start + 1 } else { 0 } } pub fn is_empty(&self) -> bool { self.end == self.start } pub fn iter(&self) -> RangeInclusive { // debug_assert!(self.start != self.end); RangeInclusive::new(self.start, self.end) } pub fn to_rev_ids(&self) -> Vec { self.iter().collect::>() } } #[inline] pub fn md5>(data: T) -> String { let md5 = format!("{:x}", md5::compute(data)); md5 } #[derive(Debug, ProtoBuf_Enum, Clone, Eq, PartialEq)] pub enum RevType { DeprecatedLocal = 0, DeprecatedRemote = 1, } impl std::default::Default for RevType { fn default() -> Self { RevType::DeprecatedLocal } }