use itertools::Itertools;
use std::collections::HashSet;
use std::fmt;
use streaming_iterator::StreamingIterator;
use crate::Data;
use crate::Ldd;
use crate::Storage;
use crate::iterators::*;
pub struct LddDot<'a> {
storage: &'a Storage,
ldd: &'a Ldd,
}
impl<'a> LddDot<'a> {
pub fn new(storage: &'a Storage, ldd: &'a Ldd) -> LddDot<'a> {
LddDot { storage, ldd }
}
}
impl fmt::Display for LddDot<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
r#"
digraph "DD" {{
graph [dpi = 300];
center = true;
edge [dir = forward];
"#
)?;
#[allow(clippy::mutable_key_type)]
let mut marked: HashSet<Ldd> = HashSet::new();
if self.ldd == self.storage.empty_set() {
writeln!(f, "0 [shape=record, label=\"False\"];")?;
} else if self.ldd == self.storage.empty_vector() {
writeln!(f, "1 [shape=record, label=\"True\"];")?;
} else {
print_node(self.storage, f, &mut marked, self.ldd)?;
}
writeln!(f, "}}")
}
}
pub struct LddDisplay<'a> {
storage: &'a Storage,
ldd: &'a Ldd,
}
impl<'a> LddDisplay<'a> {
pub fn new(storage: &'a Storage, ldd: &'a Ldd) -> LddDisplay<'a> {
LddDisplay { storage, ldd }
}
}
impl fmt::Display for LddDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "{{")?;
let mut iter = iter(self.storage, self.ldd);
while let Some(vector) = iter.next() {
writeln!(f, "\t[{}]", vector.iter().format(" "))?;
}
write!(f, "}}")
}
}
#[allow(clippy::mutable_key_type)]
fn print_node(storage: &Storage, f: &mut fmt::Formatter<'_>, marked: &mut HashSet<Ldd>, ldd: &Ldd) -> fmt::Result {
if marked.contains(ldd) || ldd == storage.empty_set() || ldd == storage.empty_vector() {
Ok(())
} else {
write!(f, "{} [shape=record, label=\"", ldd.index())?;
let mut first = true;
for Data(value, _, _) in iter_right(storage, ldd) {
if !first {
write!(f, "|")?;
}
write!(f, "<{value}> {value}")?;
first = false;
}
writeln!(f, "\"];")?;
for Data(value, down, _) in iter_right(storage, ldd) {
if down != *storage.empty_set() && down != *storage.empty_vector() {
writeln!(
f,
"{}:{} -> {}:{};",
ldd.index(),
value,
down.index(),
storage.get_ref(&down).0
)?;
}
}
for Data(_, down, _) in iter_right(storage, ldd) {
print_node(storage, f, marked, &down)?;
}
Ok(())
}
}