use std::io::Write;
use dbus::blocking::{self, stdintf::org_freedesktop_dbus::Introspectable};
use dbus_codegen::{self, ConnectionType, GenOpts};
const DESTINATION_SYSTEMD: &str = "org.freedesktop.systemd1";
const OBJECT_PATH_SYSTEMD_MANAGER: &str = "/org/freedesktop/systemd1";
const INTROSPECT_TIMEOUT_SECS: u64 = 10;
const OUTPUT_MANAGER_OBJECT_CLIENT: &str = "src/manager";
const MODULE_BLOCKING: &str = "blocking.rs";
const MODULE_NONBLOCK: &str = "nonblock.rs";
struct Generator<'a> {
output: Option<&'a str>,
object_path: Option<&'a str>,
connection_type: Option<ConnectionType>,
}
impl<'a> Generator<'a> {
pub fn new() -> Self {
Generator {
output: None,
object_path: None,
connection_type: None,
}
}
pub fn output(mut self, output: &'a str) -> Self {
self.output = Some(output);
self
}
pub fn object_path(mut self, object_path: &'a str) -> Self {
self.object_path = Some(object_path);
self
}
pub fn connection_type(mut self, connection_type: ConnectionType) -> Self {
self.connection_type = Some(connection_type);
self
}
fn introspect(object_path: &str) -> anyhow::Result<String> {
let connection = blocking::Connection::new_system()?;
let proxy = connection.with_proxy(
DESTINATION_SYSTEMD,
object_path,
std::time::Duration::from_secs(INTROSPECT_TIMEOUT_SECS),
);
let definition = proxy.introspect()?;
Ok(definition)
}
fn write<P>(path: P, bytes: &[u8]) -> anyhow::Result<()>
where
P: AsRef<std::path::Path>,
{
let mut file = std::fs::File::create(path)?;
file.write_all(bytes)?;
file.flush()?;
Ok(())
}
pub fn generate(self) -> anyhow::Result<()> {
let output = self.output.expect("output directory undefined");
let object_path = self.object_path.expect("object path undefined");
let connection_type = self.connection_type.expect("connection type undefined");
let output = match &connection_type {
ConnectionType::Blocking => format!("{}/{}", output, MODULE_BLOCKING),
ConnectionType::Nonblock => format!("{}/{}", output, MODULE_NONBLOCK),
_ => unreachable!(),
};
let definition = Self::introspect(object_path)?;
let opts = GenOpts {
connectiontype: connection_type,
methodtype: None,
..Default::default()
};
let code = dbus_codegen::generate(definition.as_str(), &opts).unwrap();
Self::write(output, code.as_bytes())?;
Ok(())
}
}
fn main() {
Generator::new()
.object_path(OBJECT_PATH_SYSTEMD_MANAGER)
.output(OUTPUT_MANAGER_OBJECT_CLIENT)
.connection_type(ConnectionType::Blocking)
.generate()
.unwrap();
Generator::new()
.object_path(OBJECT_PATH_SYSTEMD_MANAGER)
.output(OUTPUT_MANAGER_OBJECT_CLIENT)
.connection_type(ConnectionType::Nonblock)
.generate()
.unwrap();
}