swh_graph_grpc_server/
graph.rs

1// Copyright (C) 2025  The Software Heritage developers
2// See the AUTHORS file at the top-level directory of this distribution
3// License: GNU General Public License version 3, or any later version
4// See top-level LICENSE file for more information
5
6use std::iter::{empty, Empty};
7use std::path::Path;
8
9use swh_graph::arc_iterators::{LabeledArcIterator, LabeledSuccessorIterator};
10use swh_graph::graph::*;
11use swh_graph::properties;
12
13/// Alias for structures representing a graph with all arcs, arc labels, and node properties
14/// loaded (conditional on them being actually present on disk)
15pub trait SwhFullGraphWithOptProperties:
16    SwhLabeledForwardGraph
17    + SwhLabeledBackwardGraph
18    + SwhGraphWithProperties<
19        Maps: properties::Maps,
20        Timestamps: properties::OptTimestamps,
21        Persons: properties::OptPersons,
22        Contents: properties::OptContents,
23        Strings: properties::OptStrings,
24        LabelNames: properties::LabelNames,
25    >
26{
27}
28
29impl<
30        G: SwhLabeledForwardGraph
31            + SwhLabeledBackwardGraph
32            + SwhGraphWithProperties<
33                Maps: properties::Maps,
34                Timestamps: properties::OptTimestamps,
35                Persons: properties::OptPersons,
36                Contents: properties::OptContents,
37                Strings: properties::OptStrings,
38                LabelNames: properties::LabelNames,
39            >,
40    > SwhFullGraphWithOptProperties for G
41{
42}
43
44pub trait SwhOptFullGraph: SwhFullGraphWithOptProperties {}
45impl<G: SwhFullGraphWithOptProperties> SwhOptFullGraph for G {}
46
47/// Wrapper for a graph that "implements" labels by returning empty lists
48pub struct StubLabels<G: SwhGraph>(G);
49
50impl<G: SwhGraph> StubLabels<G> {
51    pub fn new(graph: G) -> Self {
52        StubLabels(graph)
53    }
54}
55
56impl<G: SwhGraph> SwhGraph for StubLabels<G> {
57    #[inline(always)]
58    fn path(&self) -> &Path {
59        self.0.path()
60    }
61    #[inline(always)]
62    fn is_transposed(&self) -> bool {
63        self.0.is_transposed()
64    }
65    #[inline(always)]
66    fn num_nodes(&self) -> usize {
67        self.0.num_nodes()
68    }
69    #[inline(always)]
70    fn has_node(&self, node_id: NodeId) -> bool {
71        self.0.has_node(node_id)
72    }
73    #[inline(always)]
74    fn num_arcs(&self) -> u64 {
75        self.0.num_arcs()
76    }
77    #[inline(always)]
78    fn has_arc(&self, src_node_id: NodeId, dst_node_id: NodeId) -> bool {
79        self.0.has_arc(src_node_id, dst_node_id)
80    }
81}
82
83impl<G: SwhForwardGraph> SwhForwardGraph for StubLabels<G> {
84    type Successors<'succ>
85        = <G as SwhForwardGraph>::Successors<'succ>
86    where
87        Self: 'succ;
88
89    #[inline(always)]
90    fn successors(&self, node_id: NodeId) -> Self::Successors<'_> {
91        self.0.successors(node_id)
92    }
93    #[inline(always)]
94    fn outdegree(&self, node_id: NodeId) -> usize {
95        self.0.outdegree(node_id)
96    }
97}
98
99impl<G: SwhForwardGraph> SwhLabeledForwardGraph for StubLabels<G> {
100    type LabeledArcs<'arc>
101        = LabeledArcIterator<Empty<u64>>
102    where
103        Self: 'arc;
104    type LabeledSuccessors<'arc>
105        = LabeledSuccessorIterator<
106        std::iter::Map<
107            <<G as SwhForwardGraph>::Successors<'arc> as IntoIterator>::IntoIter,
108            fn(usize) -> (usize, Empty<u64>),
109        >,
110    >
111    where
112        Self: 'arc;
113
114    #[inline(always)]
115    fn untyped_labeled_successors(&self, node_id: NodeId) -> Self::LabeledSuccessors<'_> {
116        LabeledSuccessorIterator::new(
117            self.successors(node_id)
118                .into_iter()
119                .map(succ_to_labeled_succ),
120        )
121    }
122}
123
124impl<G: SwhBackwardGraph> SwhBackwardGraph for StubLabels<G> {
125    type Predecessors<'succ>
126        = <G as SwhBackwardGraph>::Predecessors<'succ>
127    where
128        Self: 'succ;
129
130    #[inline(always)]
131    fn predecessors(&self, node_id: NodeId) -> Self::Predecessors<'_> {
132        self.0.predecessors(node_id)
133    }
134    #[inline(always)]
135    fn indegree(&self, node_id: NodeId) -> usize {
136        self.0.indegree(node_id)
137    }
138}
139
140impl<G: SwhBackwardGraph> SwhLabeledBackwardGraph for StubLabels<G> {
141    type LabeledArcs<'arc>
142        = LabeledArcIterator<Empty<u64>>
143    where
144        Self: 'arc;
145    type LabeledPredecessors<'arc>
146        = LabeledSuccessorIterator<
147        std::iter::Map<
148            <<G as SwhBackwardGraph>::Predecessors<'arc> as IntoIterator>::IntoIter,
149            fn(usize) -> (usize, Empty<u64>),
150        >,
151    >
152    where
153        Self: 'arc;
154
155    #[inline(always)]
156    fn untyped_labeled_predecessors(&self, node_id: NodeId) -> Self::LabeledPredecessors<'_> {
157        LabeledSuccessorIterator::new(
158            self.predecessors(node_id)
159                .into_iter()
160                .map(succ_to_labeled_succ),
161        )
162    }
163}
164
165impl<G: SwhGraphWithProperties> SwhGraphWithProperties for StubLabels<G> {
166    type Maps = <G as SwhGraphWithProperties>::Maps;
167    type Timestamps = <G as SwhGraphWithProperties>::Timestamps;
168    type Persons = <G as SwhGraphWithProperties>::Persons;
169    type Contents = <G as SwhGraphWithProperties>::Contents;
170    type Strings = <G as SwhGraphWithProperties>::Strings;
171    type LabelNames = <G as SwhGraphWithProperties>::LabelNames;
172
173    #[inline(always)]
174    fn properties(
175        &self,
176    ) -> &properties::SwhGraphProperties<
177        Self::Maps,
178        Self::Timestamps,
179        Self::Persons,
180        Self::Contents,
181        Self::Strings,
182        Self::LabelNames,
183    > {
184        self.0.properties()
185    }
186}
187
188/// Wrapper for a graph that "implements" backward arcs by returning empty lists
189pub struct StubBackwardArcs<G: SwhGraph>(G);
190
191impl<G: SwhGraph> StubBackwardArcs<G> {
192    #[inline(always)]
193    pub fn new(graph: G) -> Self {
194        StubBackwardArcs(graph)
195    }
196}
197
198impl<G: SwhGraph> SwhGraph for StubBackwardArcs<G> {
199    #[inline(always)]
200    fn path(&self) -> &Path {
201        self.0.path()
202    }
203    #[inline(always)]
204    fn is_transposed(&self) -> bool {
205        self.0.is_transposed()
206    }
207    #[inline(always)]
208    fn num_nodes(&self) -> usize {
209        self.0.num_nodes()
210    }
211    #[inline(always)]
212    fn has_node(&self, node_id: NodeId) -> bool {
213        self.0.has_node(node_id)
214    }
215    #[inline(always)]
216    fn num_arcs(&self) -> u64 {
217        self.0.num_arcs()
218    }
219    #[inline(always)]
220    fn has_arc(&self, src_node_id: NodeId, dst_node_id: NodeId) -> bool {
221        self.0.has_arc(src_node_id, dst_node_id)
222    }
223}
224
225impl<G: SwhForwardGraph> SwhForwardGraph for StubBackwardArcs<G> {
226    type Successors<'succ>
227        = <G as SwhForwardGraph>::Successors<'succ>
228    where
229        Self: 'succ;
230
231    #[inline(always)]
232    fn successors(&self, node_id: NodeId) -> Self::Successors<'_> {
233        self.0.successors(node_id)
234    }
235    #[inline(always)]
236    fn outdegree(&self, node_id: NodeId) -> usize {
237        self.0.outdegree(node_id)
238    }
239}
240
241#[inline(always)]
242fn succ_to_labeled_succ(node_id: NodeId) -> (NodeId, Empty<u64>) {
243    (node_id, empty())
244}
245
246impl<G: SwhLabeledForwardGraph> SwhLabeledForwardGraph for StubBackwardArcs<G> {
247    type LabeledArcs<'arc>
248        = <G as SwhLabeledForwardGraph>::LabeledArcs<'arc>
249    where
250        Self: 'arc;
251    type LabeledSuccessors<'arc>
252        = <G as SwhLabeledForwardGraph>::LabeledSuccessors<'arc>
253    where
254        Self: 'arc;
255
256    #[inline(always)]
257    fn untyped_labeled_successors(&self, node_id: NodeId) -> Self::LabeledSuccessors<'_> {
258        self.0.untyped_labeled_successors(node_id)
259    }
260}
261
262impl<G: SwhGraph> SwhBackwardGraph for StubBackwardArcs<G> {
263    type Predecessors<'succ>
264        = Empty<NodeId>
265    where
266        Self: 'succ;
267
268    #[inline(always)]
269    fn predecessors(&self, _node_id: NodeId) -> Self::Predecessors<'_> {
270        empty()
271    }
272    #[inline(always)]
273    fn indegree(&self, _node_id: NodeId) -> usize {
274        0
275    }
276}
277
278impl<G: SwhGraph> SwhLabeledBackwardGraph for StubBackwardArcs<G> {
279    type LabeledArcs<'arc>
280        = LabeledArcIterator<Empty<u64>>
281    where
282        Self: 'arc;
283    type LabeledPredecessors<'arc>
284        = LabeledSuccessorIterator<Empty<(NodeId, Empty<u64>)>>
285    where
286        Self: 'arc;
287
288    #[inline(always)]
289    fn untyped_labeled_predecessors(&self, _node_id: NodeId) -> Self::LabeledPredecessors<'_> {
290        LabeledSuccessorIterator::new(empty())
291    }
292}
293
294impl<G: SwhGraphWithProperties> SwhGraphWithProperties for StubBackwardArcs<G> {
295    type Maps = <G as SwhGraphWithProperties>::Maps;
296    type Timestamps = <G as SwhGraphWithProperties>::Timestamps;
297    type Persons = <G as SwhGraphWithProperties>::Persons;
298    type Contents = <G as SwhGraphWithProperties>::Contents;
299    type Strings = <G as SwhGraphWithProperties>::Strings;
300    type LabelNames = <G as SwhGraphWithProperties>::LabelNames;
301
302    #[inline(always)]
303    fn properties(
304        &self,
305    ) -> &properties::SwhGraphProperties<
306        Self::Maps,
307        Self::Timestamps,
308        Self::Persons,
309        Self::Contents,
310        Self::Strings,
311        Self::LabelNames,
312    > {
313        self.0.properties()
314    }
315}
316
317/// Empty implementation of [`properties::LabelNames`] that never returns values
318pub struct StubLabelNames;
319
320pub struct EmptyGetIndex<Output>(std::marker::PhantomData<Output>);
321impl<Output> swh_graph::utils::GetIndex for EmptyGetIndex<Output> {
322    type Output = Output;
323    #[inline(always)]
324    fn len(&self) -> usize {
325        0
326    }
327    #[inline(always)]
328    fn get(&self, _: usize) -> std::option::Option<<Self as swh_graph::utils::GetIndex>::Output> {
329        None
330    }
331    unsafe fn get_unchecked(&self, _: usize) -> <Self as swh_graph::utils::GetIndex>::Output {
332        panic!("EmptyGetIndex::get_unchecked")
333    }
334}
335
336impl properties::LabelNames for StubLabelNames {
337    type LabelNames<'a>
338        = EmptyGetIndex<Vec<u8>>
339    where
340        Self: 'a;
341
342    #[inline(always)]
343    fn label_names(&self) -> Self::LabelNames<'_> {
344        EmptyGetIndex(std::marker::PhantomData)
345    }
346}