1use crate::Value;
2use lasso::{Key, Rodeo, RodeoReader, Spur};
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use std::cmp::Ordering;
6use std::collections::HashSet;
7use std::fmt::{Debug, Formatter};
8use std::hash::{Hash, Hasher};
9use std::rc::Rc;
10
11#[derive(Clone, Debug)]
12pub enum Graph {
13 Simple(Rc<SimpleGraph>),
14}
15
16#[cfg(feature = "serde")]
17impl Serialize for Graph {
18 fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
19 where
20 S: Serializer,
21 {
22 todo!("Serialize for Graph")
23 }
24}
25
26#[cfg(feature = "serde")]
27impl<'de> Deserialize<'de> for Graph {
28 fn deserialize<D>(_: D) -> Result<Self, D::Error>
29 where
30 D: Deserializer<'de>,
31 {
32 todo!("Deserialize for Graph")
33 }
34}
35
36impl Hash for Graph {
37 fn hash<H: Hasher>(&self, _state: &mut H) {
38 todo!("Hash for Graph")
39 }
40}
41
42impl Eq for Graph {}
43impl PartialEq for Graph {
44 fn eq(&self, _other: &Self) -> bool {
45 todo!("PartialEq for Graph")
46 }
47}
48
49impl PartialOrd for Graph {
50 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51 Some(self.cmp(other))
52 }
53}
54
55impl Ord for Graph {
56 fn cmp(&self, _other: &Self) -> Ordering {
57 todo!("Ord for Graph")
58 }
59}
60
61#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
63pub struct GNodeId(pub usize);
64
65#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
67pub struct GEdgeId(pub usize);
68
69#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
71pub struct GLabelId(pub Spur);
72
73#[derive(Clone, PartialEq, Eq)]
75pub struct GLabels(pub HashSet<GLabelId>);
76
77#[derive(Clone, PartialEq, Eq)]
79pub struct GElem {
80 pub value: Option<Value>,
81 pub labels: GLabels,
82}
83
84impl GElem {
85 pub fn new(value: Option<Value>, labels: GLabels) -> Self {
86 GElem { value, labels }
87 }
88}
89
90pub struct SimpleGraph {
92 pub nodes: Vec<GElem>,
93 pub edges: Vec<GElem>,
94 pub g_dir: Vec<(GNodeId, GEdgeId, GNodeId)>,
95 pub g_undir: Vec<(GNodeId, GEdgeId, GNodeId)>,
96 pub labels: RodeoReader,
97}
98
99impl Debug for SimpleGraph {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 f.debug_struct("SimpleGraph")
102 .field("nodes", &DebugGElems("node", &self.nodes, &self.labels))
103 .field("edges", &DebugGElems("edge", &self.edges, &self.labels))
104 .field("directed", &self.g_dir)
105 .field("undirected", &self.g_undir)
106 .finish()
107 }
108}
109
110pub(crate) struct DebugGElems<'a>(&'a str, &'a Vec<GElem>, &'a RodeoReader);
112
113pub(crate) struct DebugGElem<'a>(usize, &'a str, &'a GElem, &'a RodeoReader);
115
116impl Debug for DebugGElems<'_> {
117 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
118 let mut l = f.debug_list();
119
120 for (id, gelem) in self.1.iter().enumerate() {
121 l.entry(&DebugGElem(id, self.0, gelem, self.2));
122 }
123
124 l.finish()
125 }
126}
127
128impl Debug for DebugGElem<'_> {
129 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
130 let DebugGElem(id, name, GElem { value, labels, .. }, reader) = self;
131 let labels = labels
132 .0
133 .iter()
134 .map(|id| reader.resolve(&id.0))
135 .collect::<Vec<_>>();
136 f.debug_struct(name)
137 .field("id", id)
138 .field("value", value)
139 .field("labels", &labels)
140 .finish()
141 }
142}
143
144pub enum EdgeSpec {
146 Directed(String, String), Undirected(String, String), }
149
150type NodeSpec = (Vec<String>, Vec<HashSet<String>>, Vec<Option<Value>>);
156
157#[allow(clippy::type_complexity)]
164type EdgesSpec = (
165 Vec<String>,
166 Vec<HashSet<String>>,
167 Vec<EdgeSpec>,
168 Vec<Option<Value>>,
169);
170
171impl SimpleGraph {
172 pub fn from_spec(node_specs: NodeSpec, edge_specs: EdgesSpec) -> Self {
173 let mut node_ids = Rodeo::default();
174 let mut label_ids = Rodeo::default();
175 let mut nodes: Vec<GElem> = vec![];
176
177 let (ids, labels, values) = node_specs;
179 assert_eq!(ids.len(), labels.len());
180 assert_eq!(ids.len(), values.len());
181 for ((id, labels), value) in ids
182 .into_iter()
183 .zip(labels.into_iter())
184 .zip(values.into_iter())
185 {
186 let nid = node_ids.get_or_intern(id);
187 let labels: HashSet<_> = labels
188 .into_iter()
189 .map(|l| GLabelId(label_ids.get_or_intern(l)))
190 .collect();
191 let nidx = nid.into_usize();
192 assert_eq!(nodes.len(), nidx);
193 nodes.push(GElem::new(value, GLabels(labels)));
194 }
195
196 let mut edge_ids = Rodeo::default();
197 let mut edges: Vec<GElem> = vec![];
198
199 let mut g_dir = vec![];
200 let mut g_undir = vec![];
201
202 let (ids, labels, ends, values) = edge_specs;
204 assert_eq!(ids.len(), labels.len());
205 assert_eq!(ids.len(), ends.len());
206 assert_eq!(ids.len(), values.len());
207 for (((id, labels), edge_spec), value) in ids
208 .into_iter()
209 .zip(labels.into_iter())
210 .zip(ends.into_iter())
211 .zip(values.into_iter())
212 {
213 let eid = edge_ids.get_or_intern(id);
214 let labels: HashSet<_> = labels
215 .into_iter()
216 .map(|l| GLabelId(label_ids.get_or_intern(l)))
217 .collect();
218
219 let eidx = eid.into_usize();
220 assert_eq!(edges.len(), eidx);
221 edges.push(GElem::new(value, GLabels(labels)));
222
223 match edge_spec {
224 EdgeSpec::Directed(l, r) => {
225 let eidx = GEdgeId(eidx);
226 let lidx = GNodeId(node_ids.get(l).expect("expected node").into_usize());
227 let ridx = GNodeId(node_ids.get(r).expect("expected node").into_usize());
228 g_dir.push((lidx, eidx, ridx));
229 }
230 EdgeSpec::Undirected(l, r) => {
231 let eidx = GEdgeId(eidx);
232 let lidx = GNodeId(node_ids.get(l).expect("expected node").into_usize());
233 let ridx = GNodeId(node_ids.get(r).expect("expected node").into_usize());
234 g_undir.push((lidx, eidx, ridx));
235 }
236 }
237 }
238
239 let labels = label_ids.into_reader();
240 SimpleGraph {
241 nodes,
242 edges,
243 labels,
244 g_dir,
245 g_undir,
246 }
247 }
248}