1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub struct Version {
9 pub counter: u64,
11 pub timestamp: DateTime<Utc>,
13}
14
15impl Version {
16 pub fn initial() -> Self {
18 Self {
19 counter: 1,
20 timestamp: Utc::now(),
21 }
22 }
23
24 pub fn increment(&mut self) {
26 self.counter += 1;
27 self.timestamp = Utc::now();
28 }
29
30 pub fn next(&self) -> Self {
32 Self {
33 counter: self.counter + 1,
34 timestamp: Utc::now(),
35 }
36 }
37
38 pub fn is_newer_than(&self, other: &Version) -> bool {
40 self.counter > other.counter
41 }
42}
43
44impl Default for Version {
45 fn default() -> Self {
46 Self::initial()
47 }
48}
49
50impl std::fmt::Display for Version {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "v{}", self.counter)
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
58pub struct DocumentVersion {
59 pub counter: u64,
61 pub timestamp: DateTime<Utc>,
63 pub state_hash: [u8; 8],
65}
66
67impl DocumentVersion {
68 pub fn initial() -> Self {
70 Self {
71 counter: 1,
72 timestamp: Utc::now(),
73 state_hash: [0u8; 8],
74 }
75 }
76
77 pub fn increment(&mut self, state_hash: [u8; 8]) {
79 self.counter += 1;
80 self.timestamp = Utc::now();
81 self.state_hash = state_hash;
82 }
83
84 pub fn matches(&self, other: &DocumentVersion) -> bool {
86 self.counter == other.counter && self.state_hash == other.state_hash
87 }
88}
89
90impl Default for DocumentVersion {
91 fn default() -> Self {
92 Self::initial()
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_version_increment() {
102 let mut v = Version::initial();
103 assert_eq!(v.counter, 1);
104
105 v.increment();
106 assert_eq!(v.counter, 2);
107 }
108
109 #[test]
110 fn test_version_comparison() {
111 let v1 = Version::initial();
112 let v2 = v1.next();
113
114 assert!(v2.is_newer_than(&v1));
115 assert!(!v1.is_newer_than(&v2));
116 }
117
118 #[test]
119 fn test_document_version() {
120 let mut dv = DocumentVersion::initial();
121 let hash = [1u8; 8];
122 dv.increment(hash);
123
124 assert_eq!(dv.counter, 2);
125 assert_eq!(dv.state_hash, hash);
126 }
127}