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