doku2dot/src/parsing.rs

78 lines
3.1 KiB
Rust

use std::path::Path;
use std::fs::File;
use serde_yaml;
use super::{Host, HostKind};
/** parsing funktioniert zweischrittig
zunächst wird in from_file die yaml-datei ausgelesen, das resultat ist ein struct, dass in seinem aufbau der datei entspricht
danach wird in parse dieses in ein struct verwandelt, das dem logischen aufbau entspricht.
um das programm zu erweitern ist es am besten dinge zu Host/HostKind hinzuzufügen und dann den fehlern zu folgen.
*/
#[derive(Deserialize,Debug)]
pub struct RawHost {
ansible_host: String,
#[serde(rename = "type")]
kind: String,
mac: Option<String>,
client_of: Option<String>,
coordinate: Option<[f64;2]>,
subnet: Option<String>,
link_ssid: Option<String>,
}
impl RawHost {
/** wandelt mehr oder weniger magisch eine yaml-datei in ein RawHost um.
die magie wird von dem (de)serialisierungsframework serde bereitgestellt */
pub fn from_file(path: &Path) -> (Self, String) {
//TODO use methods .is_file and .is_dir on path and read path or path/vars depending on result
let filename = path.file_stem().expect("weird path");
let hostname = filename.to_str()
.expect(&format!("filename '{:?}' is not valid utf-8", filename)).into();
let fd = if path.is_file() {
File::open(path)
.unwrap_or_else(|err| panic!("{} in file {}", err, hostname))
} else if path.is_dir() {
let mut buf = path.to_path_buf();
buf.push("vars");
File::open(buf)
.unwrap_or_else(|err| panic!("{} in file {}", err, hostname))
} else {
panic!("{:?} does not point to either a file or a directory", path)
};
let antenna : Self = serde_yaml::from_reader(&fd)
.unwrap_or_else(|err| panic!("{} in file {}", err, hostname));
(antenna, hostname)
}
/** nimmt eine geparste datei und versucht daraus die logische struktur zu extrahieren */
pub fn parse(self, name: String) -> Host {
// sobald ein felhender eintrag bei allen gefixt ist, bitte unten missingwarn("name") durch
// missingpanic ersetzen
let missingpanic= |attr: &'static str| panic!("{} does not have the required attribute {}", name, attr);
let missingwarn = |attr: &'static str| {
eprintln!("{} does not have the required attribute {}", name, attr);
"MISSING".to_string()
};
Host
{ name: name.clone()
, ip: self.ansible_host
, kind: match self.kind.as_ref()
{ "wlan-ap" => HostKind::AccessPoint
{ mac: self.mac.unwrap_or_else(|| missingpanic("mac"))
, ssid: self.link_ssid.unwrap_or_else(|| missingwarn("link_ssid"))
, parent: self.client_of.unwrap_or_else(|| missingwarn("client_of"))
}
, "client" => HostKind::Client
{ subnet: self.subnet.unwrap_or_else(|| missingpanic("subnet"))
, coordinates: self.coordinate
, parent: self.client_of.unwrap_or_else(|| missingwarn("client_of"))
, mac: self.mac.unwrap_or_else(|| missingpanic("mac"))
, ssid: self.link_ssid.unwrap_or_else(|| missingwarn("link_ssid"))
}
, "service" => HostKind::Service
, _ => HostKind::Other
}
}
}
}