blockworx_doc/
register.rs1use crate::write_order::WriteOrder;
5use serde::Serialize;
6
7#[derive(Default, Clone, Serialize)]
12pub struct Register<T> {
13 value: T,
14 order: WriteOrder,
15}
16
17#[derive(Clone, Copy, PartialEq, Eq, Debug)]
20pub enum Applied {
21 Won,
22 LostToNewer,
23}
24
25impl<T: Clone> Register<T> {
26 pub fn new(value: &T, order: WriteOrder) -> Self {
27 Self {
28 value: value.clone(),
29 order,
30 }
31 }
32 pub fn order(&self) -> WriteOrder {
33 self.order
34 }
35 pub fn apply(&mut self, value: &T, order: WriteOrder) -> Applied {
36 if order > self.order {
37 self.value = value.clone();
38 self.order = order;
39 Applied::Won
40 } else {
41 Applied::LostToNewer
42 }
43 }
44}
45
46impl<T> AsRef<T> for Register<T> {
47 fn as_ref(&self) -> &T {
48 &self.value
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::{rev::Rev, write_order::Seq};
56
57 fn order(rev: u64, seq: usize) -> WriteOrder {
58 WriteOrder::new(Rev::new(rev), Seq::new(seq))
59 }
60
61 fn at(rev: u64) -> WriteOrder {
62 order(rev, 0)
63 }
64
65 #[test]
66 fn a_register_starts_at_its_zero_at_bottom() {
67 let register = Register::<u8>::default();
68 assert_eq!(*register.as_ref(), 0);
69 assert_eq!(register.order(), WriteOrder::BOTTOM);
70 }
71
72 #[test]
73 fn a_later_write_wins() {
74 let mut register = Register::<u8>::default();
75 assert_eq!(register.apply(&3, at(5)), Applied::Won);
76 assert_eq!(*register.as_ref(), 3);
77 assert_eq!(register.order(), at(5));
78 }
79
80 #[test]
81 fn an_earlier_write_is_dropped() {
82 let mut register = Register::<u8>::default();
83 register.apply(&3, at(5));
84 assert_eq!(register.apply(&9, at(2)), Applied::LostToNewer);
85 assert_eq!(*register.as_ref(), 3, "the stale write must not land");
86 assert_eq!(register.order(), at(5));
87 }
88
89 #[test]
92 fn a_commits_second_write_to_one_register_wins_by_seq() {
93 let (first, second) = (order(5, 0), order(5, 1));
94 assert_eq!(
95 first.rev, second.rev,
96 "the fixture must share a rev or the seq isn't what's ordering them"
97 );
98
99 let mut register = Register::<u8>::default();
100 assert_eq!(register.apply(&1, first), Applied::Won);
101 assert_eq!(register.apply(&2, second), Applied::Won);
102 assert_eq!(*register.as_ref(), 2);
103 }
104
105 #[test]
108 fn re_delivering_a_write_changes_nothing() {
109 let mut register = Register::<u8>::default();
110 register.apply(&3, at(5));
111 assert_eq!(register.apply(&3, at(5)), Applied::LostToNewer);
112 assert_eq!(*register.as_ref(), 3);
113 assert_eq!(register.order(), at(5));
114 }
115}