1use super::*;
2use std::cmp::max;
3
4#[cfg(feature = "serialization")]
5use serde_derive::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, Default, Eq, PartialEq)]
13#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
14pub struct Register<T, Tag, CL>
15where
16 T: Key,
17 Tag: TagT,
18 CL: CausalLength,
19{
20 pub(crate) item: T,
21 pub(crate) tag: Tag,
22 pub(crate) length: CL,
23}
24
25impl<T, Tag, CL> Register<T, Tag, CL>
26where
27 T: Key,
28 Tag: TagT,
29 CL: CausalLength,
30{
31 pub fn new(item: T, tag: Tag) -> Register<T, Tag, CL> {
33 Register {
34 item,
35 tag,
36 length: CL::one(),
37 }
38 }
39
40 pub(crate) fn make<I>(item: I, tag: Tag, length: CL) -> Register<T, Tag, CL>
41 where
42 I: Into<T>,
43 {
44 Register {
45 item: item.into(),
46 tag,
47 length,
48 }
49 }
50
51 pub fn get(&self) -> Option<(&T, Tag)> {
53 match &self {
54 Register { item, tag, length } if length.is_odd() => Some((item, *tag)),
55 _ => None,
56 }
57 }
58
59 pub fn set(&mut self, item: T, tag: Tag) {
61 self.item = item;
62 self.tag = max(self.tag, tag);
63
64 if self.length.is_odd() {
65 self.length = self.length + CL::one() + CL::one();
66 } else {
67 self.length = self.length + CL::one();
68 }
69 }
70
71 pub fn clear(&mut self, tag: Tag) {
73 if self.length.is_odd() {
74 self.length = self.length + CL::one();
75 self.tag = max(self.tag, tag);
76 }
77 }
78
79 pub fn item(&self) -> &T {
81 &self.item
82 }
83
84 pub fn tag(&self) -> Tag {
86 self.tag
87 }
88
89 pub fn length(&self) -> CL {
91 self.length
92 }
93}
94
95impl<T, Tag, CL> Register<T, Tag, CL>
96where
97 T: Key + Ord,
98 Tag: TagT,
99 CL: CausalLength,
100{
101 pub fn merge(&mut self, other: &Register<T, Tag, CL>) {
103 if other.length > self.length && other.length.is_odd() {
104 self.item = other.item.clone();
105 self.tag = other.tag;
106 }
107 if other.length == self.length {
108 if other.tag > self.tag {
109 self.item = other.item.clone();
110 self.tag = max(self.tag, other.tag);
111 } else if other.tag == self.tag && other.item > self.item {
112 self.item = other.item.clone();
113 }
114 }
115 self.length = max(self.length, other.length);
116 }
117}
118
119#[cfg(test)]
120use quickcheck::{Arbitrary, Gen};
121#[cfg(test)]
122impl<T, Tag, CL> Arbitrary for Register<T, Tag, CL>
123where
124 T: Key + Arbitrary,
125 Tag: TagT + Arbitrary,
126 CL: CausalLength + Arbitrary,
127{
128 fn arbitrary(g: &mut Gen) -> Register<T, Tag, CL> {
129 Register::make(T::arbitrary(g), Tag::arbitrary(g), CL::arbitrary(g))
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use quickcheck_macros::quickcheck;
137
138 #[test]
139 fn test_merge() {
140 let mut reg1: Register<&str, u32, u16> = Register::new("foo", 0);
141 let mut reg2 = reg1.clone();
142 let mut reg3 = reg1.clone();
143
144 reg3.clear(2);
145 reg2.set("bar", 2);
146
147 reg1.merge(®2);
148 reg1.merge(®3);
149
150 assert_eq!(reg1, reg2);
151 assert_eq!(reg1.length, 3);
152 assert_eq!(reg1.get(), Some((&"bar", 2)));
153 }
154
155 #[cfg(feature = "serialization")]
156 #[test]
157 fn test_serialization() {
158 let reg1: Register<&str, u32, u16> = Register::new("foo", 0);
159 let data = serde_json::to_string(®1).unwrap();
160 assert_eq!(&data, r#"{"item":"foo","tag":0,"length":1}"#);
161 }
162
163 fn merge(mut acc: Register<u8, u8, u8>, el: &Register<u8, u8, u8>) -> Register<u8, u8, u8> {
164 acc.merge(el);
165 acc
166 }
167
168 #[quickcheck]
169 fn is_merge_commutative(xs: Vec<Register<u8, u8, u8>>) -> bool {
170 let left = xs.iter().fold(Register::default(), merge);
171 let right = xs.iter().rfold(Register::default(), merge);
172 left.get() == right.get()
173 }
174
175 #[test]
176 fn test_fup() {
177 let xs = vec![
178 Register {
179 item: 255,
180 tag: 174,
181 length: 1,
182 },
183 Register {
184 item: 9,
185 tag: 162,
186 length: 176,
187 },
188 ];
189 let left = xs.iter().fold(Register::default(), merge);
190 let right = xs.iter().rfold(Register::default(), merge);
191 assert_eq!(left.get(), right.get());
192 }
193}