1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::{cmp::Ordering, sync::Arc};
use loro_common::HasLamport;
use rle::HasLength;
use crate::{
change::{Change, Lamport, Timestamp},
id::ID,
version::Frontiers,
};
/// `Change` is a grouped continuous operations that share the same id, timestamp, commit message.
///
/// - The id of the `Change` is the id of its first op.
/// - The second op's id is `{ peer: change.id.peer, counter: change.id.counter + 1 }`
///
/// The same applies on `Lamport`:
///
/// - The lamport of the `Change` is the lamport of its first op.
/// - The second op's lamport is `change.lamport + 1`
///
/// The length of the `Change` is how many operations it contains
#[derive(Debug, Clone)]
pub struct ChangeMeta {
/// Lamport timestamp of the Change
pub lamport: Lamport,
/// The first Op id of the Change
pub id: ID,
/// [Unix time](https://en.wikipedia.org/wiki/Unix_time)
/// It is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970.
pub timestamp: Timestamp,
/// The commit message of the change
pub message: Option<Arc<str>>,
/// The dependencies of the first op of the change
pub deps: Frontiers,
/// The total op num inside this change
pub len: usize,
}
impl PartialEq for ChangeMeta {
fn eq(&self, other: &Self) -> bool {
self.lamport == other.lamport && self.id == other.id
}
}
impl Eq for ChangeMeta {}
impl PartialOrd for ChangeMeta {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ChangeMeta {
fn cmp(&self, other: &Self) -> Ordering {
(self.lamport + self.len as Lamport)
.cmp(&(other.lamport + other.len as Lamport))
.then(self.id.peer.cmp(&other.id.peer))
}
}
impl HasLamport for ChangeMeta {
fn lamport(&self) -> loro_common::Lamport {
self.lamport
}
}
impl HasLength for ChangeMeta {
fn content_len(&self) -> usize {
self.len
}
}
impl ChangeMeta {
pub fn from_change(c: &Change) -> Self {
Self {
id: c.id(),
lamport: c.lamport(),
timestamp: c.timestamp(),
message: c.message().cloned(),
deps: c.deps().clone(),
len: c.len(),
}
}
/// Get the commit message in &str
pub fn message(&self) -> &str {
match self.message.as_ref() {
Some(m) => m,
None => "",
}
}
/// Get the commit timestamp in seconds since Unix epoch.
pub fn timestamp(&self) -> crate::change::Timestamp {
self.timestamp
}
}