1use super::change_id::*;
2use super::{BASE32, L64};
3#[cfg(test)]
4use quickcheck::{Arbitrary, Gen};
5
6#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
9#[repr(C)]
10pub struct Vertex<H> {
11 pub change: H,
13 pub start: ChangePosition,
17 pub end: ChangePosition,
18}
19
20impl<T: std::fmt::Debug> std::fmt::Debug for Vertex<T> {
21 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
22 write!(
23 fmt,
24 "V({:?}[{}:{}])",
25 self.change,
26 (self.start.0),
27 (self.end.0)
28 )
29 }
30}
31
32impl Vertex<ChangeId> {
33 pub const ROOT: Vertex<ChangeId> = Vertex {
35 change: ChangeId::ROOT,
36 start: ChangePosition::ROOT,
37 end: ChangePosition::ROOT,
38 };
39
40 pub const MAX: Vertex<ChangeId> = Vertex {
41 change: ChangeId(L64(u64::MAX)),
43 start: ChangePosition(L64(u64::MAX)),
44 end: ChangePosition(L64(u64::MAX)),
45 };
46
47 pub(crate) const BOTTOM: Vertex<ChangeId> = Vertex {
49 change: ChangeId::ROOT,
50 start: ChangePosition::BOTTOM,
51 end: ChangePosition::BOTTOM,
52 };
53
54 pub fn is_root(&self) -> bool {
56 self == &Vertex::ROOT
57 }
58
59 pub fn to_option(&self) -> Vertex<Option<ChangeId>> {
60 Vertex {
61 change: Some(self.change),
62 start: self.start,
63 end: self.end,
64 }
65 }
66}
67
68impl<H: Clone> Vertex<H> {
69 pub fn start_pos(&self) -> Position<H> {
73 Position {
74 change: self.change.clone(),
75 pos: self.start,
76 }
77 }
78
79 pub fn end_pos(&self) -> Position<H> {
83 Position {
84 change: self.change.clone(),
85 pos: self.end,
86 }
87 }
88
89 pub fn is_empty(&self) -> bool {
91 self.end == self.start
92 }
93
94 pub fn len(&self) -> usize {
96 self.end - self.start
97 }
98}
99#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
101pub struct ChangePosition(pub super::L64);
102
103impl ChangePosition {
104 pub(crate) const ROOT: ChangePosition = ChangePosition(L64(0u64));
105 pub(crate) const BOTTOM: ChangePosition = ChangePosition(L64(1u64.to_le()));
106}
107
108impl std::ops::Add<usize> for ChangePosition {
109 type Output = ChangePosition;
110 fn add(self, x: usize) -> Self::Output {
111 ChangePosition(self.0 + x)
112 }
113}
114
115impl std::ops::Sub<ChangePosition> for ChangePosition {
116 type Output = usize;
117 fn sub(self, x: ChangePosition) -> Self::Output {
118 let a: u64 = self.0.into();
119 let b: u64 = x.0.into();
120 (a - b) as usize
121 }
122}
123
124#[cfg(test)]
125impl Arbitrary for ChangePosition {
126 fn arbitrary(g: &mut Gen) -> Self {
127 ChangePosition(L64(u64::arbitrary(g)))
128 }
129 fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
130 Box::new(self.0.0.shrink().map(|x| ChangePosition(L64(x))))
131 }
132}
133
134impl ChangePosition {
135 pub(crate) fn us(&self) -> usize {
136 u64::from_le((self.0).0) as usize
137 }
138}
139
140impl From<ChangePosition> for u64 {
141 fn from(f: ChangePosition) -> u64 {
142 u64::from_le((f.0).0)
143 }
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
148#[doc(hidden)]
149#[repr(C)]
150pub struct Position<P> {
151 pub change: P,
152 pub pos: ChangePosition,
153}
154
155use super::Base32;
156
157impl<H: super::Base32> Base32 for Position<H> {
158 fn to_base32(&self) -> String {
159 let mut v = self.change.to_base32();
160 let mut bytes = [0; 8];
161 self.pos.0.to_slice_le(&mut bytes);
162 let mut i = 7;
163 while i > 2 && bytes[i] == 0 {
164 i -= 1
165 }
166 i += 1;
167 let len = BASE32.encode_len(i);
168 let len0 = v.len() + 1;
169 v.push_str("..............");
170 v.truncate(len0 + len);
171 BASE32.encode_mut(&bytes[..i], unsafe {
172 v.split_at_mut(len0).1.as_bytes_mut()
173 });
174 v
175 }
176 fn from_base32(s: &[u8]) -> Option<Self> {
177 let n = s.iter().position(|c| *c == b'.')?;
178 let (s, pos) = s.split_at(n);
179 let pos = &pos[1..];
180 let change = H::from_base32(s)?;
181 let mut dec = [0; 8];
182 let len = BASE32.decode_len(pos.len()).ok()?;
183 let pos = BASE32
184 .decode_mut(pos, &mut dec[..len])
185 .map(|_| L64::from_slice_le(&dec))
186 .ok()?;
187 Some(Position {
188 change,
189 pos: ChangePosition(pos),
190 })
191 }
192}
193
194pub mod position_base32_serde {
195 use super::*;
196 use serde::*;
197
198 pub struct PositionDe {}
199
200 impl<'de> serde::de::Visitor<'de> for PositionDe {
201 type Value = Position<ChangeId>;
202
203 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
204 write!(formatter, "a base32-encoded string")
205 }
206
207 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
208 where
209 E: de::Error,
210 {
211 if let Some(b) = Position::from_base32(s.as_bytes()) {
212 Ok(b)
213 } else {
214 Err(de::Error::invalid_value(
215 serde::de::Unexpected::Str(s),
216 &self,
217 ))
218 }
219 }
220 }
221
222 pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Position<ChangeId>, D::Error> {
223 d.deserialize_str(PositionDe {})
224 }
225
226 pub fn serialize<S: Serializer>(pos: &Position<ChangeId>, s: S) -> Result<S::Ok, S::Error> {
227 let b = pos.to_base32();
228 s.serialize_str(&b)
229 }
230}
231
232impl<H> std::ops::Add<usize> for Position<H> {
233 type Output = Position<H>;
234 fn add(self, x: usize) -> Self::Output {
235 Position {
236 change: self.change,
237 pos: self.pos + x,
238 }
239 }
240}
241
242impl<H> Position<Option<H>> {
243 pub fn unwrap(self) -> Position<H> {
244 Position {
245 change: self.change.unwrap(),
246 pos: self.pos,
247 }
248 }
249}
250
251impl<H> Vertex<Option<H>> {
252 pub fn unwrap(self) -> Vertex<H> {
253 Vertex {
254 change: self.change.unwrap(),
255 start: self.start,
256 end: self.end,
257 }
258 }
259}
260
261impl Position<ChangeId> {
262 pub fn inode_vertex(&self) -> Vertex<ChangeId> {
263 Vertex {
264 change: self.change,
265 start: self.pos,
266 end: self.pos,
267 }
268 }
269
270 pub fn is_root(&self) -> bool {
271 self.change.is_root()
272 }
273
274 pub fn to_option(&self) -> Position<Option<ChangeId>> {
275 Position {
276 change: Some(self.change),
277 pos: self.pos,
278 }
279 }
280
281 pub const ROOT: Position<ChangeId> = Position {
282 change: ChangeId::ROOT,
283 pos: ChangePosition(L64(0u64)),
284 };
285
286 pub(crate) const OPTION_ROOT: Position<Option<ChangeId>> = Position {
287 change: Some(ChangeId::ROOT),
288 pos: ChangePosition(L64(0u64)),
289 };
290
291 pub(crate) const BOTTOM: Position<ChangeId> = Position {
292 change: ChangeId::ROOT,
293 pos: ChangePosition::BOTTOM,
294 };
295}