Skip to main content

pijul_core/pristine/
edge.rs

1use super::L64;
2use super::change_id::*;
3use super::vertex::*;
4
5bitflags! {
6    /// Possible flags of edges.
7    #[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
8    pub struct EdgeFlags: u8 {
9        const BLOCK = 1;
10        /// A pseudo-edge, computed when applying the change to
11        /// restore connectivity, and/or mark conflicts.
12        const PSEUDO = 4;
13        /// An edge encoding file system hierarchy.
14        const FOLDER = 16;
15        /// A "reverse" edge (all edges in the graph have a reverse edge).
16        const PARENT = 32;
17        /// An edge whose target (if not also `PARENT`) or
18        /// source (if also `PARENT`) is marked as deleted.
19        const DELETED = 128;
20    }
21}
22
23impl EdgeFlags {
24    #[inline]
25    pub(crate) fn df() -> Self {
26        Self::DELETED | Self::FOLDER
27    }
28
29    #[inline]
30    pub(crate) fn pseudof() -> Self {
31        Self::PSEUDO | Self::FOLDER
32    }
33
34    #[inline]
35    pub(crate) fn alive_children() -> Self {
36        Self::BLOCK | Self::PSEUDO | Self::FOLDER
37    }
38
39    #[inline]
40    pub(crate) fn parent_folder() -> Self {
41        Self::PARENT | Self::FOLDER
42    }
43
44    #[inline]
45    pub fn is_deleted(&self) -> bool {
46        self.contains(EdgeFlags::DELETED)
47    }
48
49    #[inline]
50    pub fn is_alive_parent(&self) -> bool {
51        *self & (EdgeFlags::DELETED | EdgeFlags::PARENT) == EdgeFlags::PARENT
52    }
53    #[inline]
54    pub fn is_parent(&self) -> bool {
55        self.contains(EdgeFlags::PARENT)
56    }
57    #[inline]
58    pub fn is_folder(&self) -> bool {
59        self.contains(EdgeFlags::FOLDER)
60    }
61    #[inline]
62    pub fn is_block(&self) -> bool {
63        self.contains(EdgeFlags::BLOCK)
64    }
65}
66
67/// The target half of an edge in the repository graph.
68#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
69#[doc(hidden)]
70pub struct Edge {
71    /// Flags of this edge.
72    pub flag: EdgeFlags,
73    /// Target of this edge.
74    pub dest: Position<ChangeId>,
75    /// Change that introduced this edge (possibly as a
76    /// pseudo-edge, i.e. not explicitly in the change, but
77    /// computed from it).
78    pub introduced_by: ChangeId,
79}
80
81/// The target half of an edge in the repository graph.
82#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
83pub struct SerializedEdge([super::L64; 3]);
84
85impl std::fmt::Debug for SerializedEdge {
86    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
87        let pos = self.dest();
88        use super::Base32;
89        write!(
90            fmt,
91            "E({:?}, {}[{}], {})",
92            self.flag(),
93            pos.change.to_base32(),
94            (pos.pos.0).0,
95            self.introduced_by().to_base32()
96        )
97    }
98}
99
100impl std::ops::SubAssign<EdgeFlags> for SerializedEdge {
101    fn sub_assign(&mut self, e: EdgeFlags) {
102        let f = &mut (self.0)[0];
103        f.0 = ((u64::from_le(f.0)) & !((e.bits() as u64) << 56)).to_le()
104    }
105}
106
107impl SerializedEdge {
108    pub fn flag(&self) -> EdgeFlags {
109        let f = u64::from_le((self.0)[0].0);
110        EdgeFlags::from_bits((f >> 56) as u8).unwrap()
111    }
112    pub fn dest(&self) -> Position<ChangeId> {
113        let pos = u64::from_le((self.0[0]).0);
114        Position {
115            change: ChangeId((self.0)[1]),
116            pos: ChangePosition(L64((pos & 0xffffffffffffff).to_le())),
117        }
118    }
119    pub fn introduced_by(&self) -> ChangeId {
120        ChangeId((self.0)[2])
121    }
122}
123
124impl From<SerializedEdge> for Edge {
125    fn from(s: SerializedEdge) -> Edge {
126        Edge {
127            flag: s.flag(),
128            dest: s.dest(),
129            introduced_by: s.introduced_by(),
130        }
131    }
132}
133
134impl From<Edge> for SerializedEdge {
135    fn from(s: Edge) -> SerializedEdge {
136        let pos = u64::from_le((s.dest.pos.0).0);
137        assert!(pos < 1 << 56);
138        SerializedEdge([
139            (((s.flag.bits() as u64) << 56) | pos).into(),
140            s.dest.change.0,
141            s.introduced_by.0,
142        ])
143    }
144}
145
146impl<'a> From<&'a SerializedEdge> for Edge {
147    fn from(s: &'a SerializedEdge) -> Edge {
148        Edge {
149            flag: s.flag(),
150            dest: s.dest(),
151            introduced_by: s.introduced_by(),
152        }
153    }
154}
155impl SerializedEdge {
156    pub fn empty(dest: Position<ChangeId>, intro: ChangeId) -> Self {
157        SerializedEdge([dest.pos.0, dest.change.0, intro.0])
158    }
159
160    pub fn new(flag: EdgeFlags, change: ChangeId, pos: ChangePosition, intro: ChangeId) -> Self {
161        let pos = pos.0.as_u64();
162        assert!(pos < 1 << 56);
163        SerializedEdge([
164            (pos | ((flag.bits() as u64) << 56)).into(),
165            change.0,
166            intro.0,
167        ])
168    }
169}