1use std::collections::HashMap;
11use std::ops::AddAssign;
12
13#[cfg(feature = "display")]
14use std::fmt::{Display, Formatter};
15
16use crate::subgraph_free::{
17 AttrStmt as AstAttrStmt, EdgeStmt, Graph as SFGraph, NodeID, NodeStmt, Port, Stmt,
18};
19
20pub use crate::ast::AList;
21
22#[derive(Debug, Clone)]
27pub struct Graph<A> {
28 pub strict: bool,
32 pub is_digraph: bool,
34 pub name: Option<String>,
36 pub attr: Vec<AttrStmt<A>>,
38 pub nodes: NodeSet<A>,
40 pub edges: EdgeSet<A>,
42 pub ideqs: Vec<IDEq>,
44}
45
46#[cfg(feature = "display")]
47impl<A> Display for Graph<A>
48where
49 A: Display,
50{
51 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
52 if self.strict {
53 write!(f, "strict ")?;
54 }
55 if self.is_digraph {
56 write!(f, "digraph ")?;
57 } else {
58 write!(f, "graph ")?;
59 }
60 if let Some(name) = &self.name {
61 write!(f, "{}", name)?;
62 }
63
64 writeln!(f, "{{")?;
65 for stmt in &self.attr {
66 writeln!(f, "{}", stmt)?;
67 }
68
69 for ideq in &self.ideqs {
70 writeln!(f, "{}", ideq)?;
71 }
72
73 write!(f, "{}", self.nodes)?;
74 write!(f, "{}", self.edges)?;
75 writeln!(f, "}}")?;
76
77 Result::Ok(())
78 }
79}
80
81impl<A> Graph<A> {
82 pub fn filter_map<F, B>(self, f: F) -> Graph<B>
90 where
91 F: Fn(A) -> Option<B>,
92 {
93 let new_attr = self
94 .attr
95 .into_iter()
96 .filter_map(|attr_stmt| attr_stmt.filter_map(&f))
97 .collect();
98 let new_nodes = self.nodes.map(&f);
99 let new_edges = self.edges.map(&f);
100
101 Graph {
102 strict: self.strict,
103 is_digraph: self.is_digraph,
104 name: self.name,
105 attr: new_attr,
106 nodes: new_nodes,
107 edges: new_edges,
108 ideqs: self.ideqs,
109 }
110 }
111}
112
113impl<A, G> From<G> for Graph<A>
114where
115 G: Into<SFGraph<A>>,
116 A: Clone,
117{
118 fn from(graph: G) -> Self {
119 let graph = graph.into();
120 let mut attrs: Vec<AstAttrStmt<_>> = Vec::new();
121 let mut nodes = Vec::new();
122 let mut edges = Vec::new();
123 let mut ideqs = Vec::new();
124
125 for stmt in graph.stmts {
126 match stmt {
127 Stmt::NodeStmt(node) => nodes.push(node),
128 Stmt::EdgeStmt(edge) => edges.push(edge),
129 Stmt::AttrStmt(attr) => attrs.push(attr),
130 Stmt::IDEq(lhs, rhs) => ideqs.push(IDEq {lhs, rhs}),
131 }
132 }
133
134 let mut nodes: NodeSet<A> = nodes.into();
135 let edges: EdgeSet<A> = (edges, &mut nodes).into();
136 let attr: Vec<AttrStmt<A>> = attrs
137 .into_iter()
138 .flat_map(|stmt: AstAttrStmt<_>| {
139 let attr_l: Vec<AttrStmt<A>> = stmt.into();
140 attr_l
141 })
142 .collect();
143
144 Graph {
145 strict: graph.strict,
146 is_digraph: graph.is_digraph,
147 name: graph.name,
148 attr,
149 nodes,
150 edges,
151 ideqs,
152 }
153 }
154}
155
156#[derive(Debug, Clone)]
158pub struct Node<A> {
159 pub id: String,
161 pub port: Option<Port>,
163 pub attr: AList<A>,
165}
166
167impl<A> From<NodeStmt<A>> for Node<A> {
168 fn from(stmt: NodeStmt<A>) -> Self {
169 Node {
170 id: stmt.node.id.to_string(),
171 port: stmt.node.port,
172 attr: stmt.attr.map(|list| list.into()).unwrap_or(AList::empty()),
173 }
174 }
175}
176
177impl<A> From<&NodeID> for Node<A> {
178 fn from(node: &NodeID) -> Self {
179 Node {
180 id: node.id.to_string(),
181 port: node.port.clone(),
182 attr: AList::empty(),
183 }
184 }
185}
186
187impl<A> Node<A> {
188 fn map<F, B>(self, f: F) -> Node<B>
189 where
190 F: Fn(A) -> Option<B>,
191 {
192 Node {
193 id: self.id,
194 port: self.port,
195 attr: self.attr.filter_map_attr(&f),
196 }
197 }
198}
199
200#[cfg(feature = "display")]
201impl<A> Display for Node<A>
202where
203 A: Display,
204{
205 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
206 write!(f, "\"{}\" ", self.id)?;
207 if let Some(port) = &self.port {
208 write!(f, "{}", port)?;
209 }
210 if !self.attr.is_empty() {
211 write!(f, "[{}]", self.attr)?;
212 }
213
214 Ok(())
215 }
216}
217
218#[derive(Debug, Clone)]
220pub struct NodeSet<A> {
221 pub set: HashMap<String, Node<A>>,
224}
225
226impl<A> NodeSet<A> {
227 fn insert_if_absent(&mut self, id: String, or: Node<A>) {
228 if self.set.get(&id).is_none() {
230 self.set.insert(id, or);
231 }
232 }
233
234 fn map<F, B>(self, f: F) -> NodeSet<B>
235 where
236 F: Fn(A) -> Option<B>,
237 {
238 let new_set = self
239 .set
240 .into_iter()
241 .map(|(name, node)| (name, node.map(&f)))
242 .collect();
243 NodeSet { set: new_set }
244 }
245}
246
247impl<A, I> From<I> for NodeSet<A>
248where
249 I: IntoIterator<Item = NodeStmt<A>>,
250{
251 fn from(nodes: I) -> Self {
252 let set: HashMap<_, _> = nodes
253 .into_iter()
254 .map(|node| (node.node.id.to_string(), node.into()))
255 .collect();
256 NodeSet { set }
257 }
258}
259
260#[cfg(feature = "display")]
261impl<A> Display for NodeSet<A>
262where
263 A: Display,
264{
265 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
266 for node in self.set.values() {
267 writeln!(f, "{}", node)?;
268 }
269
270 Ok(())
271 }
272}
273
274#[derive(Debug, Clone)]
276pub struct EdgeSet<A> {
277 pub set: Vec<Edge<A>>,
279}
280
281impl<A> EdgeSet<A> {
282 fn empty() -> Self {
283 Self { set: Vec::new() }
284 }
285
286 fn map<F, B>(self, f: F) -> EdgeSet<B>
287 where
288 F: Fn(A) -> Option<B>,
289 {
290 let new_set = self.set.into_iter().map(|edge| edge.map(&f)).collect();
291 EdgeSet { set: new_set }
292 }
293}
294
295impl<A> AddAssign for EdgeSet<A> {
296 fn add_assign(&mut self, mut rhs: Self) {
297 self.set.append(&mut rhs.set)
298 }
299}
300
301#[cfg(feature = "display")]
302impl<A> Display for EdgeSet<A>
303where
304 A: Display,
305{
306 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
307 for edge in &self.set {
308 writeln!(f, "{}", edge)?;
309 }
310 Ok(())
311 }
312}
313
314#[derive(Debug, Clone, Eq, PartialEq)]
317pub struct Edge<A> {
318 pub from: String,
320 pub to: String,
322 pub attr: AList<A>,
324}
325
326#[cfg(feature = "display")]
327impl<A> Display for Edge<A>
328where
329 A: Display,
330{
331 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
332 write!(f, "\"{}\" -> \"{}\" [{}]", self.from, self.to, self.attr)
333 }
334}
335
336impl<A> Edge<A> {
337 fn map<F, B>(self, f: F) -> Edge<B>
338 where
339 F: Fn(A) -> Option<B>,
340 {
341 Edge {
342 from: self.from,
343 to: self.to,
344 attr: self.attr.filter_map_attr(&f),
345 }
346 }
347}
348
349impl<A> From<(EdgeStmt<A>, &mut NodeSet<A>)> for EdgeSet<A>
350where
351 A: Clone,
352{
353 fn from(tuple: (EdgeStmt<A>, &mut NodeSet<A>)) -> Self {
354 let (stmt, nodes) = tuple;
355 let mut from = stmt.from;
356 let mut rhs = stmt.next;
357 let mut set = Vec::new();
358 let attr = stmt.attr.map(|list| list.into()).unwrap_or(AList::empty());
359
360 loop {
361 let to = rhs.to;
362 let from_id = from.id.clone();
363 let to_id = to.id.clone();
364
365 nodes.insert_if_absent(from.id.to_string(), (&from).into());
366 nodes.insert_if_absent(to.id.to_string(), (&to).into());
367
368 let edge = Edge {
369 from: from_id.to_string(),
370 to: to_id.to_string(),
371 attr: attr.clone(),
372 };
373
374 set.push(edge);
375
376 if rhs.next.is_none() {
377 return EdgeSet { set };
378 }
379 from = to;
380 rhs = *(rhs.next.unwrap());
381 }
382 }
383}
384
385impl<A, I> From<(I, &mut NodeSet<A>)> for EdgeSet<A>
386where
387 I: IntoIterator<Item = EdgeStmt<A>>,
388 A: Clone,
389{
390 fn from(tuple: (I, &mut NodeSet<A>)) -> Self {
391 let (stmts, nodes) = tuple;
392 let mut set = EdgeSet::empty();
393 for stmt in stmts {
394 set += (stmt, &mut *nodes).into();
395 }
396 set
397 }
398}
399
400#[derive(Debug, Copy, Clone)]
401pub enum AttrStmt<A> {
405 Graph(A),
407 Node(A),
409 Edge(A),
411}
412
413impl<A> AttrStmt<A> {
414 fn filter_map<F, B>(self, f: F) -> Option<AttrStmt<B>>
415 where
416 F: Fn(A) -> Option<B>,
417 {
418 match self {
419 AttrStmt::Graph(a) => {
420 f(a).map(AttrStmt::Graph)
421 }
422 AttrStmt::Node(a) => {
423 f(a).map(AttrStmt::Node)
424 }
425 AttrStmt::Edge(a) => {
426 f(a).map(AttrStmt::Edge)
427 }
428 }
429 }
430}
431
432impl<A> From<AstAttrStmt<A>> for Vec<AttrStmt<A>> {
433 fn from(val: AstAttrStmt<A>) -> Self {
434 match val {
435 AstAttrStmt::Graph(list) => {
436 let alist: AList<A> = list.into();
437 alist
438 .into_iter()
439 .map(|attr| AttrStmt::Graph(attr))
440 .collect()
441 }
442 AstAttrStmt::Node(list) => {
443 let alist: AList<A> = list.into();
444 alist
445 .into_iter()
446 .map(|attr| AttrStmt::Node(attr))
447 .collect()
448 }
449 AstAttrStmt::Edge(list) => {
450 let alist: AList<A> = list.into();
451 alist
452 .into_iter()
453 .map(|attr| AttrStmt::Edge(attr))
454 .collect()
455 }
456 }
457 }
458}
459
460#[cfg(feature = "display")]
461impl<A> Display for AttrStmt<A>
462where
463 A: Display,
464{
465 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
466 match self {
467 AttrStmt::Graph(attr) => write!(f, "graph [{}]", attr),
468 AttrStmt::Edge(attr) => write!(f, "edge [{}]", attr),
469 AttrStmt::Node(attr) => write!(f, "node [{}]", attr),
470 }
471 }
472}
473
474#[derive(Clone, Debug)]
475pub struct IDEq {
477 pub lhs: String,
479 pub rhs: String,
481}
482
483#[cfg(feature = "display")]
484impl Display for IDEq {
485 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
486 write!(f, "{} = {}", self.lhs, self.rhs)
487 }
488}