graphannis_core/graph/storage/
union.rs

1use super::EdgeContainer;
2use crate::{
3    errors::{GraphAnnisCoreError, Result},
4    types::NodeID,
5};
6use rustc_hash::FxHashSet;
7
8pub struct UnionEdgeContainer<'a> {
9    containers: Vec<&'a dyn EdgeContainer>,
10}
11
12impl<'a> UnionEdgeContainer<'a> {
13    pub fn new(containers: Vec<&'a dyn EdgeContainer>) -> UnionEdgeContainer<'a> {
14        UnionEdgeContainer { containers }
15    }
16}
17
18impl EdgeContainer for UnionEdgeContainer<'_> {
19    fn get_outgoing_edges<'b>(
20        &'b self,
21        node: NodeID,
22    ) -> Box<dyn Iterator<Item = Result<NodeID>> + 'b> {
23        // Use a hash set so target nodes are only returned once
24        let mut targets: FxHashSet<NodeID> = FxHashSet::default();
25        // Collect all possible errors when trying to get the outgoing edges
26        let mut errors: Vec<GraphAnnisCoreError> = Vec::new();
27        for c in self.containers.iter() {
28            let outgoing: Result<Vec<NodeID>> = c.get_outgoing_edges(node).collect();
29            match outgoing {
30                Ok(outgoing) => targets.extend(outgoing),
31                Err(e) => errors.push(e),
32            }
33        }
34        if errors.is_empty() {
35            Box::from(targets.into_iter().map(Ok))
36        } else {
37            // Only return the errors
38            Box::from(errors.into_iter().map(Err))
39        }
40    }
41
42    fn get_ingoing_edges<'b>(
43        &'b self,
44        node: NodeID,
45    ) -> Box<dyn Iterator<Item = Result<NodeID>> + 'b> {
46        // Use a hash set so target nodes are only returned once
47        let mut sources: FxHashSet<NodeID> = FxHashSet::default();
48        // Collect all possible errors when trying to get the outgoing edges
49        let mut errors: Vec<GraphAnnisCoreError> = Vec::new();
50        for c in self.containers.iter() {
51            let ingoing: Result<Vec<NodeID>> = c.get_ingoing_edges(node).collect();
52            match ingoing {
53                Ok(ingoing) => sources.extend(ingoing),
54                Err(e) => errors.push(e),
55            }
56        }
57        if errors.is_empty() {
58            Box::from(sources.into_iter().map(Ok))
59        } else {
60            // Only return the errors
61            Box::from(errors.into_iter().map(Err))
62        }
63    }
64
65    fn source_nodes<'b>(&'b self) -> Box<dyn Iterator<Item = Result<NodeID>> + 'b> {
66        let mut sources: FxHashSet<NodeID> = FxHashSet::default();
67        for c in self.containers.iter() {
68            for n in c.source_nodes() {
69                match n {
70                    Ok(n) => sources.insert(n),
71                    Err(e) => return Box::new(std::iter::once(Err(e))),
72                };
73            }
74        }
75        Box::from(sources.into_iter().map(Ok))
76    }
77}