doku2dot/src/main.rs

151 lines
4.4 KiB
Rust
Raw Permalink Normal View History

2017-11-17 00:18:59 +01:00
#[macro_use]
extern crate serde_derive;
extern crate serde_yaml;
use std::path::Path;
mod parsing;
2017-11-17 00:18:59 +01:00
fn main() {
//read the files
//let paths = [Path::new("test.yml")];
let filenames: Vec<_> = std::env::args_os().skip(1).collect();
let hosts: Vec<Host> = filenames.iter()
.map(Path::new)
.map(|path| Host::from_file(&path))
.collect();
//build dot-graph
let nodes = hosts.iter().map(Host::to_dot_node);
let edges = hosts.iter().flat_map(Host::to_dot_edge);
//render it
2017-11-17 02:14:12 +01:00
println!("graph antennen {{");
2017-11-17 00:18:59 +01:00
for node in nodes {
println!("{}", node);
}
for edge in edges {
println!("{}", edge);
}
println!("}}");
}
#[derive(Debug)]
pub struct Host {
2017-11-17 00:18:59 +01:00
name: String,
ip: String,
2020-06-23 20:38:50 +02:00
parent: String,
2017-11-17 00:18:59 +01:00
kind: HostKind,
}
impl Host {
fn from_file(path: &Path) -> Self {
let (host, hostname) = parsing::RawHost::from_file(path);
host.parse(hostname)
2017-11-17 00:18:59 +01:00
}
fn to_dot_node(&self) -> String {
let mut attributes = vec!
[ "shape=record".to_string()
, "style=filled".into()
];
let record;
2017-11-17 00:18:59 +01:00
// type-specific handling
use HostKind::*;
2017-11-17 00:18:59 +01:00
match self.kind {
Client {coordinates, ref subnet, ref mac, .. } =>
2017-11-17 02:14:12 +01:00
{ attributes.push("fillcolor=lightgray".into())
; if let Some(coordinates) = coordinates
{ attributes.push(format!("pos=\"{breitengrad},{längengrad}\""
, längengrad=coordinates[0], breitengrad=coordinates[1]))
}
; record =
( self.name.clone()
, (self.kind.name(), mac.clone())
, (self.ip.clone(), subnet.clone())
, ("no ipv6", "no 6-subnet")
).recordify()
2017-11-17 02:14:12 +01:00
},
AccessPoint { ref mac, .. } => record =
( self.name.clone()
, (self.kind.name(), mac.clone() )
, self.ip.clone()
).recordify(),
_ => record = (self.name.clone(), self.kind.name(), self.ip.clone()).recordify(),
2017-11-17 00:18:59 +01:00
};
attributes.push(format!("label=\"{}\"", record));
2017-11-17 00:18:59 +01:00
let attributes = attributes.join(", ");
format!("\"{name}\" [{attributes}]", name=self.name, attributes=attributes)
}
fn to_dot_edge(&self) -> Option<String> {
match self.kind {
2020-06-23 20:38:50 +02:00
HostKind::Client { ref ssid, .. } =>
format!("\"{name}\" -- \"{parent}\" [label=\"{ssid}\"]", name=self.name, parent=self.parent, ssid=ssid).into(),
// hier eventuelle ausnahmen für bestimmte typen die keine parents haben eintragen
// mainly template und sol
_ =>
format!("\"{name}\" -- \"{parent}\"", name=self.name, parent=self.parent).into(),
2017-11-17 00:18:59 +01:00
}
}
}
#[derive(Debug)]
enum HostKind {
2020-06-23 20:38:50 +02:00
Client { mac: String, subnet: String, coordinates: Option<[f64;2]>, ssid: String },
AccessPoint { mac: String, ssid: String },
Service,
2017-11-17 00:18:59 +01:00
Other,
}
impl HostKind {
fn name(&self) -> &'static str {
use HostKind::*;
match *self {
Client { .. } => "Client",
AccessPoint { .. } => "AccessPoint",
Service => "Service",
2017-11-17 00:18:59 +01:00
Other => "Other",
}
}
}
/** dieser Trait ermöglicht es verschachtelte tupel in ein label für einen record-shaped-node für
dotfiles umzuwandeln. inputwerte werden nicht escaped
assert_eq!(
("a", ("b", "c", "d"), ("e","f"), "g").recordify(),
"{a|{b|c|d}|{e|f}|g}".into())
*/
pub trait DotRecord {
fn recordify(self) -> String;
2017-11-17 00:18:59 +01:00
}
impl DotRecord for String {
fn recordify(self) -> String { self }
}
impl<'a> DotRecord for &'a str {
fn recordify(self) -> String { self.into() }
}
impl<A: DotRecord, B: DotRecord> DotRecord for (A,B) {
fn recordify(self) -> String {
format!("{{{}|{}}}", self.0.recordify(), self.1.recordify())
}
}
impl<A: DotRecord, B: DotRecord, C: DotRecord> DotRecord for (A,B,C) {
fn recordify(self) -> String {
format!("{{{}|{}|{}}}", self.0.recordify(), self.1.recordify(), self.2.recordify())
}
}
impl<A: DotRecord, B: DotRecord, C: DotRecord, D: DotRecord> DotRecord for (A,B,C,D) {
fn recordify(self) -> String {
format!("{{{}|{}|{}|{}}}", self.0.recordify(), self.1.recordify(), self.2.recordify(), self.3.recordify())
}
}
impl<A: DotRecord, B: DotRecord, C: DotRecord, D: DotRecord, E: DotRecord> DotRecord for (A,B,C,D,E) {
fn recordify(self) -> String {
format!("{{{}|{}|{}|{}|{}}}", self.0.recordify(), self.1.recordify(), self.2.recordify(), self.3.recordify(), self.4.recordify())
}
2017-11-17 00:18:59 +01:00
}