1#![allow(dead_code)]
4
5#[derive(Debug, Clone, PartialEq)]
9pub enum ChangeKind {
10 Added,
11 Modified,
12 Deleted,
13 Renamed,
14}
15
16#[derive(Debug, Clone)]
18pub struct ChangeEntry {
19 pub id: u64,
20 pub kind: ChangeKind,
21 pub path: String,
22 pub author: String,
23 pub description: String,
24 pub timestamp_ms: u64,
25}
26
27#[derive(Debug, Default)]
29pub struct ChangeLog {
30 entries: Vec<ChangeEntry>,
31 next_id: u64,
32}
33
34impl ChangeLog {
35 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn append(
40 &mut self,
41 kind: ChangeKind,
42 path: &str,
43 author: &str,
44 description: &str,
45 timestamp_ms: u64,
46 ) -> u64 {
47 let id = self.next_id;
48 self.next_id += 1;
49 self.entries.push(ChangeEntry {
50 id,
51 kind,
52 path: path.to_string(),
53 author: author.to_string(),
54 description: description.to_string(),
55 timestamp_ms,
56 });
57 id
58 }
59
60 pub fn entry_count(&self) -> usize {
61 self.entries.len()
62 }
63
64 pub fn entries(&self) -> &[ChangeEntry] {
65 &self.entries
66 }
67
68 pub fn filter_kind(&self, kind: &ChangeKind) -> Vec<&ChangeEntry> {
69 self.entries.iter().filter(|e| &e.kind == kind).collect()
70 }
71
72 pub fn filter_author(&self, author: &str) -> Vec<&ChangeEntry> {
73 self.entries.iter().filter(|e| e.author == author).collect()
74 }
75
76 pub fn since(&self, timestamp_ms: u64) -> Vec<&ChangeEntry> {
77 self.entries
78 .iter()
79 .filter(|e| e.timestamp_ms >= timestamp_ms)
80 .collect()
81 }
82}
83
84pub fn new_change_log() -> ChangeLog {
85 ChangeLog::new()
86}
87
88pub fn cl_append(
89 log: &mut ChangeLog,
90 kind: ChangeKind,
91 path: &str,
92 author: &str,
93 desc: &str,
94 ts: u64,
95) -> u64 {
96 log.append(kind, path, author, desc, ts)
97}
98
99pub fn cl_count(log: &ChangeLog) -> usize {
100 log.entry_count()
101}
102
103pub fn cl_filter_kind<'a>(log: &'a ChangeLog, kind: &ChangeKind) -> Vec<&'a ChangeEntry> {
104 log.filter_kind(kind)
105}
106
107pub fn cl_since(log: &ChangeLog, ts: u64) -> Vec<&ChangeEntry> {
108 log.since(ts)
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn test_append_and_count() {
117 let mut log = new_change_log();
118 cl_append(
119 &mut log,
120 ChangeKind::Added,
121 "src/main.rs",
122 "alice",
123 "init",
124 1000,
125 );
126 assert_eq!(cl_count(&log), 1);
127 }
128
129 #[test]
130 fn test_id_increments() {
131 let mut log = new_change_log();
132 let id0 = cl_append(&mut log, ChangeKind::Added, "a", "u", "d", 0);
133 let id1 = cl_append(&mut log, ChangeKind::Modified, "b", "u", "d", 1);
134 assert_eq!(id0, 0);
135 assert_eq!(id1, 1);
136 }
137
138 #[test]
139 fn test_filter_kind_added() {
140 let mut log = new_change_log();
141 cl_append(&mut log, ChangeKind::Added, "f1", "u", "d", 0);
142 cl_append(&mut log, ChangeKind::Deleted, "f2", "u", "d", 1);
143 assert_eq!(cl_filter_kind(&log, &ChangeKind::Added).len(), 1);
144 }
145
146 #[test]
147 fn test_filter_author() {
148 let mut log = new_change_log();
149 cl_append(&mut log, ChangeKind::Added, "f", "alice", "d", 0);
150 cl_append(&mut log, ChangeKind::Added, "g", "bob", "d", 1);
151 assert_eq!(log.filter_author("alice").len(), 1);
152 }
153
154 #[test]
155 fn test_since_filter() {
156 let mut log = new_change_log();
157 cl_append(&mut log, ChangeKind::Added, "f", "u", "d", 100);
158 cl_append(&mut log, ChangeKind::Added, "g", "u", "d", 200);
159 cl_append(&mut log, ChangeKind::Added, "h", "u", "d", 300);
160 assert_eq!(cl_since(&log, 200).len(), 2);
161 }
162
163 #[test]
164 fn test_renamed_kind() {
165 let mut log = new_change_log();
166 cl_append(&mut log, ChangeKind::Renamed, "old", "u", "renamed", 0);
167 assert_eq!(cl_filter_kind(&log, &ChangeKind::Renamed).len(), 1);
168 }
169
170 #[test]
171 fn test_empty_log() {
172 let log = new_change_log();
173 assert_eq!(cl_count(&log), 0);
174 }
175
176 #[test]
177 fn test_entries_stored() {
178 let mut log = new_change_log();
179 cl_append(
180 &mut log,
181 ChangeKind::Modified,
182 "cfg.toml",
183 "dev",
184 "tweaks",
185 500,
186 );
187 assert_eq!(log.entries()[0].path, "cfg.toml");
188 }
189
190 #[test]
191 fn test_multiple_same_kind() {
192 let mut log = new_change_log();
193 for i in 0..5 {
194 cl_append(&mut log, ChangeKind::Modified, "f", "u", "d", i);
195 }
196 assert_eq!(cl_filter_kind(&log, &ChangeKind::Modified).len(), 5);
197 }
198}