diff --git a/src/main.rs b/src/main.rs index addb8d3..7f9a0df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,12 +27,8 @@ fn main() { let nodes = hosts.iter().map(Host::to_dot_node); let edges = hosts.iter().flat_map(Host::to_dot_edge); - // let edges = .. - //render it - - println!("digraph antennen {{"); - + println!("graph antennen {{"); for node in nodes { println!("{}", node); } @@ -55,15 +51,15 @@ pub enum ParseError { #[error_chain(custom)] #[error_chain(description = r#"|_| "Host file structure broken""#)] - #[error_chain(display = r#"|t| write!(f, "the antenna config is wrong: {}", t)"#)] - Structure(String), + #[error_chain(display = r#"|&(ref name, ref err)| write!(f, "the antenna config of {} is wrong: {}", name, err)"#)] + Structure((String, String)), } #[derive(Debug)] struct Host { name: String, ip: String, - mac: String, + mac: Option, kind: HostKind, } impl Host { @@ -71,20 +67,24 @@ impl Host { RawHost::from_file(path)?.parse() } fn to_dot_node(&self) -> String { + let mac = self.mac.clone().unwrap_or("no mac".into()); let mut attributes = vec! [ "shape=record".to_string() , format!("label=\"{{\'{name}\'|{typ}|{{{ip}|{mac}}}|{{{ipv6}}}}}\"" - , name = self.name, typ=self.kind.name(), ip=self.ip, mac=self.mac, ipv6="no ipv6") + , name = self.name, typ=self.kind.name(), ip=self.ip + , mac=mac, ipv6="no ipv6") , "style=filled".into() ]; // type-specific handling match self.kind { - HostKind::Client {coordinates, ref subnet, .. } => attributes.extend_from_slice( - &[ format!("pos=\"{breitengrad},{längengrad}\"" - , längengrad=coordinates[0], breitengrad=coordinates[1]) - , "fillcolor=lightgray".into() - ]), + HostKind::Client {coordinates, ref subnet, .. } => + { attributes.push("fillcolor=lightgray".into()) + ; if let Some(coordinates) = coordinates + { attributes.push(format!("pos=\"{breitengrad},{längengrad}\"" + , längengrad=coordinates[0], breitengrad=coordinates[1])) + } + }, _ => (), }; @@ -95,7 +95,7 @@ impl Host { fn to_dot_edge(&self) -> Option { match self.kind { HostKind::Client { ref parent, .. } => - format!("\"{name}\" -> \"{parent}\"", name=self.name, parent=parent).into(), + format!("\"{name}\" -- \"{parent}\"", name=self.name, parent=parent).into(), _ => None, } } @@ -103,7 +103,7 @@ impl Host { #[derive(Debug)] enum HostKind { - Client { subnet: String, coordinates: [f64;2], parent: String }, + Client { subnet: String, coordinates: Option<[f64;2]>, parent: String }, AccessPoint, Other, } @@ -127,7 +127,7 @@ struct RawHost { ansible_host: String, #[serde(rename = "type")] kind: String, - mac: String, + mac: Option, client_of: Option, coordinate: Option<[f64;2]>, subnet: Option, @@ -135,21 +135,22 @@ struct RawHost { impl RawHost { fn parse(self) -> Result { - let name = self.name - .ok_or(ParseError::Structure("got no file name? weird.".into()))? + let name : String = self.name + .ok_or(ParseError::Structure(("???".into(),"got no file name? weird.".into())))? .into_string().unwrap() .split('.') .next().unwrap().into(); Ok(Host - { name: name + { name: name.clone() , ip: self.ansible_host , mac: self.mac , kind: match self.kind.as_ref() { "wlan-ap" => HostKind::AccessPoint , "client" => HostKind::Client - { subnet: self.subnet.ok_or(ParseError::Structure("is client, has no subnet".into()))? - , coordinates: self.coordinate.ok_or(ParseError::Structure("is client, has no coordinates".into()))? - , parent: self.client_of.ok_or(ParseError::Structure("is client, has no client_of".into()))? + { subnet: self.subnet.ok_or(ParseError::Structure((name.clone(), "is client, has no subnet".into())))? + //, coordinates: self.coordinate.ok_or(ParseError::Structure("is client, has no coordinates".into()))? + , coordinates: self.coordinate + , parent: self.client_of.ok_or(ParseError::Structure((name.clone(), "is client, has no client_of".into())))? } , _ => HostKind::Other }