1pub const REMEMBERED: usize = 512;
2
3pub fn hash(text: &str) -> u64 {
4 text.bytes().fold(0xcbf2_9ce4_8422_2325, |hash, byte| {
5 (hash ^ u64::from(byte)).wrapping_mul(0x0000_0100_0000_01b3)
6 })
7}
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
10pub struct Stamp {
11 pub len: u64,
12 pub hash: u64,
13}
14
15impl Stamp {
16 pub fn of(text: &str) -> Stamp {
17 Stamp {
18 len: text.len() as u64,
19 hash: hash(text),
20 }
21 }
22}
23
24#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25pub enum Seen {
26 Current,
27 Earlier,
28 Outside,
29}
30
31#[derive(Clone, Debug, PartialEq, Eq)]
32pub enum Disk {
33 Same,
34 Own,
35 Outside(String),
36 Missing,
37}
38
39#[derive(Clone, Debug, Default, PartialEq, Eq)]
40pub struct Own {
41 current: Option<Stamp>,
42 written: Vec<Stamp>,
43}
44
45impl Own {
46 pub fn read(&mut self, text: &str) {
47 self.current = Some(Stamp::of(text));
48 }
49
50 pub fn wrote(&mut self, text: &str) -> Stamp {
51 let stamp = Stamp::of(text);
52 self.current = Some(stamp);
53 self.written.retain(|known| *known != stamp);
54 self.written.push(stamp);
55 if self.written.len() > REMEMBERED {
56 self.written.remove(0);
57 }
58 stamp
59 }
60
61 pub fn current(&self) -> Option<Stamp> {
62 self.current
63 }
64
65 pub fn seen(&self, stamp: Stamp) -> Seen {
66 if self.current == Some(stamp) {
67 Seen::Current
68 } else if self.written.contains(&stamp) {
69 Seen::Earlier
70 } else {
71 Seen::Outside
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn a_stamp_is_the_length_and_the_hash() {
82 assert_eq!(Stamp::of(""), Stamp::of(""));
83 assert_ne!(Stamp::of("a = 1\n"), Stamp::of("a = 2\n"));
84 assert_eq!(Stamp::of("abc").len, 3);
85 assert_eq!(hash(""), 0xcbf2_9ce4_8422_2325);
86 }
87
88 #[test]
89 fn own_writes_are_told_from_outside_ones() {
90 let mut own = Own::default();
91 own.read("a = 1\n");
92 assert_eq!(own.seen(Stamp::of("a = 1\n")), Seen::Current);
93 own.wrote("a = 2\n");
94 own.wrote("a = 3\n");
95 assert_eq!(own.seen(Stamp::of("a = 3\n")), Seen::Current);
96 assert_eq!(own.seen(Stamp::of("a = 2\n")), Seen::Earlier);
97 assert_eq!(own.seen(Stamp::of("a = 1\n")), Seen::Outside);
98 assert_eq!(own.seen(Stamp::of("a = 4\n")), Seen::Outside);
99 }
100
101 #[test]
102 fn only_the_last_writes_are_remembered() {
103 let mut own = Own::default();
104 for step in 0..REMEMBERED + 2 {
105 own.wrote(&step.to_string());
106 }
107 assert_eq!(own.seen(Stamp::of("0")), Seen::Outside);
108 assert_eq!(own.seen(Stamp::of("2")), Seen::Earlier);
109 }
110}