From 92a611581f51f7a4d5727302ecf5848978d6d4c0 Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Thu, 14 Dec 2023 21:08:33 +0000 Subject: [PATCH] Generate dbus bindings from xml descriptions --- Cargo.lock | 17 +++++++++ Cargo.toml | 3 ++ build.rs | 81 +++++++++++++++++++++++++++++++++++++++++++ flake.nix | 9 ++++- src/generated.rs | 3 ++ src/main.rs | 1 + src/tiles/hostname.rs | 4 +-- 7 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 build.rs create mode 100644 src/generated.rs diff --git a/Cargo.lock b/Cargo.lock index ca0c737..6aab309 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,6 +213,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "dbus-codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76dc35ce83e4e9fa089b4fabe66c757b27bd504dc2179c97a01b36d3e874fb0" +dependencies = [ + "clap", + "xml-rs", +] + [[package]] name = "dbus-tokio" version = "0.7.6" @@ -993,6 +1003,7 @@ dependencies = [ "chrono", "chrono-tz", "dbus", + "dbus-codegen", "dbus-tokio", "eyre", "local-ip-address", @@ -1742,3 +1753,9 @@ dependencies = [ "cfg-if", "windows-sys 0.48.0", ] + +[[package]] +name = "xml-rs" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" diff --git a/Cargo.toml b/Cargo.toml index eb6770e..4cbca8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,9 @@ tokio-stream = { version = "0.1", features = ["time"]} toml = "0.8" uuid = { version = "1.4", features = [ "v4" ] } +[build-dependencies] +dbus-codegen = { version = "0.10", default-features = false } + [profile.release] incremental = false codegen-units = 1 diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..8fbd7e7 --- /dev/null +++ b/build.rs @@ -0,0 +1,81 @@ +use std::collections::HashSet; +use std::env; +use std::fs; +use std::io::Read; +use std::io::Write; +use std::path::Path; + +use dbus_codegen::ConnectionType; +use dbus_codegen::GenOpts; + +fn main() { + println!("cargo:rerun-if-env-changed=DBUS_XML_PATH"); + println!("cargo:rerun-if-changed=build.rs"); + + let required_files = HashSet::from(["org.freedesktop.hostname1.xml"]); + let required_interfaces = required_files + .iter() + .map(|name| name.strip_suffix(".xml").unwrap().to_string()) + .collect(); + + let opts = GenOpts { + connectiontype: ConnectionType::Nonblock, + methodtype: None, + interfaces: Some(required_interfaces), + ..Default::default() + }; + + let out_dir_str = env::var("OUT_DIR").unwrap(); + let out_dir = Path::new(&out_dir_str); + + let mut generated_file = fs::File::create(out_dir.join("generated.rs")).unwrap(); + + let dbus_paths_raw = + env::var("DBUS_XML_PATH").unwrap_or("/usr/share/dbus-1/interfaces".to_string()); + dbus_paths_raw + .split(':') + .map(fs::read_dir) + .flat_map(Result::unwrap) + .map(Result::unwrap) + .filter(|file| required_files.contains(file.file_name().to_str().unwrap())) + .for_each(|in_file| { + println!( + "cargo:rerun-if-changed={}", + in_file.path().to_str().unwrap() + ); + + let mut xml = String::new(); + fs::File::open(in_file.path()) + .unwrap() + .read_to_string(&mut xml) + .unwrap(); + + let code = dbus_codegen::generate(&xml, &opts).unwrap(); + + let module_name = in_file + .file_name() + .into_string() + .unwrap() + .strip_suffix(".xml") + .unwrap() + .replace('.', "_"); + let out_path = out_dir.join(module_name.clone() + ".rs"); + fs::File::create(out_path) + .unwrap() + .write_all(code.as_bytes()) + .unwrap(); + + generated_file + .write_all( + format!( + r#"mod {module_name} {{ + include!(concat!(env!("OUT_DIR"), "/{module_name}.rs")); + }} + pub use {module_name}::*; + "# + ) + .as_bytes(), + ) + .unwrap(); + }) +} diff --git a/flake.nix b/flake.nix index a181cf9..62f2f57 100644 --- a/flake.nix +++ b/flake.nix @@ -9,7 +9,11 @@ outputs = { self, nixpkgs, utils }: let supportedSystems = [ "x86_64-linux" "aarch64-linux" ]; in (utils.lib.eachSystem supportedSystems (system: - let pkgs = import nixpkgs { inherit system; }; + let + pkgs = import nixpkgs { inherit system; }; + inherit (pkgs) lib; + dbusPaths = lib.makeSearchPathOutput "out" "share/dbus-1/interfaces" + (with pkgs; [ systemd ]); in rec { packages.rustybar = with pkgs; rustPlatform.buildRustPackage { @@ -21,6 +25,8 @@ nativeBuildInputs = [ pkg-config ]; buildInputs = [ dbus ]; + DBUS_XML_PATH = dbusPaths; + meta = with lib; { homepage = "https://github.com/mildlyfunctionalgays/rustybar"; description = "swaybar/i3bar command in Rust"; @@ -45,6 +51,7 @@ rustPackages.rustfmt rustPackages.clippy ]; + DBUS_XML_PATH = dbusPaths; RUST_SRC_PATH = "${rustPackages.rustPlatform.rustLibSrc}/lib/rustlib"; }; diff --git a/src/generated.rs b/src/generated.rs new file mode 100644 index 0000000..dd0ae94 --- /dev/null +++ b/src/generated.rs @@ -0,0 +1,3 @@ +#![allow(clippy::needless_borrow)] + +include!(concat!(env!("OUT_DIR"), "/generated.rs")); diff --git a/src/main.rs b/src/main.rs index 8f6552b..13ddb0f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod config; +mod generated; mod output; mod tile; mod tiles; diff --git a/src/tiles/hostname.rs b/src/tiles/hostname.rs index c4be8a5..933720e 100644 --- a/src/tiles/hostname.rs +++ b/src/tiles/hostname.rs @@ -1,7 +1,7 @@ use crate::config::HostnameConfig; +use crate::generated::OrgFreedesktopHostname1; use crate::output::OutputChannel; use crate::tile::Block; -use dbus::nonblock::stdintf::org_freedesktop_dbus::Properties; use dbus::nonblock::{Proxy, SyncConnection}; use std::sync::Arc; use std::time::Duration; @@ -19,7 +19,7 @@ pub async fn hostname( ); let mut interval = tokio::time::interval(config.update); loop { - let reply = proxy.get("org.freedesktop.hostname1", "Hostname"); + let reply = proxy.hostname(); let hostname: String = reply.await?; output .send(Block {