From 090fa264b8151f6fe86a8aff367b13fb1557eb3b Mon Sep 17 00:00:00 2001 From: Zeeshan Ali Khan Date: Fri, 18 Aug 2023 16:22:57 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A9=B9=20zn:=20Remove=20unneeded=20us?= =?UTF-8?q?e=20of=20`allow(clippy::upper=5Fcase=5Facronyms)`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pretty sure this was a copy&paste error. --- zbus_names/src/error.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zbus_names/src/error.rs b/zbus_names/src/error.rs index d77f2e730..778529238 100644 --- a/zbus_names/src/error.rs +++ b/zbus_names/src/error.rs @@ -6,7 +6,6 @@ use zvariant::Error as VariantError; /// /// The various errors that can be reported by this crate. #[derive(Clone, Debug)] -#[allow(clippy::upper_case_acronyms)] #[non_exhaustive] pub enum Error { Variant(VariantError), From b93560b51863cd00971facc5ed97a2d8ba6bd83c Mon Sep 17 00:00:00 2001 From: Zeeshan Ali Khan Date: Fri, 18 Aug 2023 14:11:26 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=9A=9A=20Move=20xml=20mod=20into=20a?= =?UTF-8?q?=20separate=20crate,=20zbus=5Fxml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #413. --- Cargo.toml | 1 + zbus/Cargo.toml | 6 +- zbus/src/error.rs | 20 ------ zbus/src/lib.rs | 3 - zbus/tests/e2e.rs | 62 ++++++++--------- zbus_xml/Cargo.toml | 27 ++++++++ zbus_xml/README.md | 17 +++++ zbus_xml/src/error.rs | 66 +++++++++++++++++++ zbus/src/xml.rs => zbus_xml/src/lib.rs | 45 ++++++------- .../tests/data/invalid_arg_type.xml | 0 .../tests/data/sample_object0.xml | 0 zbus/tests/xml.rs => zbus_xml/tests/tests.xml | 7 +- zbus_xmlgen/Cargo.toml | 3 +- zbus_xmlgen/src/lib.rs | 6 +- zbus_xmlgen/src/main.rs | 2 +- zbus_xmlgen/tests/gen.rs | 2 +- 16 files changed, 169 insertions(+), 98 deletions(-) create mode 100644 zbus_xml/Cargo.toml create mode 100644 zbus_xml/README.md create mode 100644 zbus_xml/src/error.rs rename zbus/src/xml.rs => zbus_xml/src/lib.rs (87%) rename {zbus => zbus_xml}/tests/data/invalid_arg_type.xml (100%) rename {zbus => zbus_xml}/tests/data/sample_object0.xml (100%) rename zbus/tests/xml.rs => zbus_xml/tests/tests.xml (87%) diff --git a/Cargo.toml b/Cargo.toml index d7db175ed..dc2e0bc6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "zvariant_derive", "zvariant_utils", "zbus_macros", + "zbus_xml", "zbus_xmlgen", ] resolver = "2" diff --git a/zbus/Cargo.toml b/zbus/Cargo.toml index 510a97311..ef75f14d2 100644 --- a/zbus/Cargo.toml +++ b/zbus/Cargo.toml @@ -32,7 +32,6 @@ async-io = [ tokio = ["dep:tokio"] vsock = ["dep:vsock", "dep:async-io"] tokio-vsock = ["dep:tokio-vsock", "tokio"] -xml = ["dep:quick-xml"] [dependencies] byteorder = "1.4.3" @@ -80,10 +79,6 @@ tokio = { version = "1.21.2", optional = true, features = [ tracing = "0.1.37" vsock = { version = "0.3.0", optional = true } tokio-vsock = { version = "0.3.3", optional = true } -quick-xml = { version = "0.27.1", features = [ - "serialize", - "overlapped-lists", -], optional = true } xdg-home = "1.0.0" [target.'cfg(windows)'.dependencies] @@ -117,6 +112,7 @@ async-process = "1.7.0" async-recursion = "1.0.0" [dev-dependencies] +zbus_xml = { path = "../zbus_xml", version = "4.0.0" } doc-comment = "0.3.3" futures-util = "0.3.25" # activate default features ntest = "0.9.0" diff --git a/zbus/src/error.rs b/zbus/src/error.rs index 819925265..3ab0b3ea1 100644 --- a/zbus/src/error.rs +++ b/zbus/src/error.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "xml")] -use quick_xml::de::DeError; use static_assertions::assert_impl_all; use std::{convert::Infallible, error, fmt, io, sync::Arc}; use zbus_names::{Error as NamesError, OwnedErrorName}; @@ -49,9 +47,6 @@ pub enum Error { Unsupported, /// A [`fdo::Error`] transformed into [`Error`]. FDO(Box), - #[cfg(feature = "xml")] - /// An XML error from quick_xml - QuickXml(DeError), /// The requested name was already claimed by another peer. NameTaken, /// Invalid [match rule][MR] string. @@ -89,8 +84,6 @@ impl PartialEq for Error { (Self::Names(s), Self::Names(o)) => s == o, (Self::NameTaken, Self::NameTaken) => true, (Error::InputOutput(_), Self::InputOutput(_)) => false, - #[cfg(feature = "xml")] - (Self::QuickXml(_), Self::QuickXml(_)) => false, (Self::Failure(s1), Self::Failure(s2)) => s1 == s2, (_, _) => false, } @@ -113,8 +106,6 @@ impl error::Error for Error { Error::InvalidGUID => None, Error::Unsupported => None, Error::FDO(e) => Some(e), - #[cfg(feature = "xml")] - Error::QuickXml(e) => Some(e), Error::InvalidField => None, Error::MissingField => None, Error::NameTaken => None, @@ -149,8 +140,6 @@ impl fmt::Display for Error { Error::InvalidGUID => write!(f, "Invalid GUID"), Error::Unsupported => write!(f, "Connection support is lacking"), Error::FDO(e) => write!(f, "{e}"), - #[cfg(feature = "xml")] - Error::QuickXml(e) => write!(f, "XML error: {e}"), Error::NameTaken => write!(f, "name already taken on the bus"), Error::InvalidMatchRule => write!(f, "Invalid match rule string"), Error::Failure(e) => write!(f, "{e}"), @@ -182,8 +171,6 @@ impl Clone for Error { Error::InvalidGUID => Error::InvalidGUID, Error::Unsupported => Error::Unsupported, Error::FDO(e) => Error::FDO(e.clone()), - #[cfg(feature = "xml")] - Error::QuickXml(e) => Error::QuickXml(e.clone()), Error::NameTaken => Error::NameTaken, Error::InvalidMatchRule => Error::InvalidMatchRule, Error::Failure(e) => Error::Failure(e.clone()), @@ -230,13 +217,6 @@ impl From for Error { } } -#[cfg(feature = "xml")] -impl From for Error { - fn from(val: DeError) -> Self { - Error::QuickXml(val) - } -} - impl From for Error { fn from(i: Infallible) -> Self { match i {} diff --git a/zbus/src/lib.rs b/zbus/src/lib.rs index 9408503c8..1a40deb81 100644 --- a/zbus/src/lib.rs +++ b/zbus/src/lib.rs @@ -172,9 +172,6 @@ pub use connection::Socket; pub mod blocking; -#[cfg(feature = "xml")] -pub mod xml; - pub use zbus_macros::{dbus_interface, dbus_proxy, DBusError}; // Required for the macros to function within this crate. diff --git a/zbus/tests/e2e.rs b/zbus/tests/e2e.rs index d14828b5e..494009640 100644 --- a/zbus/tests/e2e.rs +++ b/zbus/tests/e2e.rs @@ -17,7 +17,7 @@ use zbus::{ fdo::{ObjectManager, ObjectManagerProxy}, message::{self, Builder}, object_server::ResponseDispatchNotifier, - DBusError, MessageStream, + DBusError, Error, MessageStream, }; use zvariant::{DeserializeDict, Optional, OwnedValue, SerializeDict, Str, Type, Value}; @@ -529,39 +529,35 @@ async fn my_iface_test(conn: Connection, event: Event) -> zbus::Result { assert_eq!(proxy.optional_property().await?, Some(42).into()); - #[cfg(feature = "xml")] - { - let xml = proxy.introspect().await?; - debug!("Introspection: {}", xml); - #[cfg(feature = "xml")] - let node = zbus::xml::Node::from_reader(xml.as_bytes())?; - let ifaces = node.interfaces(); - let iface = ifaces + let xml = proxy.introspect().await?; + debug!("Introspection: {}", xml); + let node = + zbus_xml::Node::from_reader(xml.as_bytes()).map_err(|e| Error::Failure(e.to_string()))?; + let ifaces = node.interfaces(); + let iface = ifaces + .iter() + .find(|i| i.name() == "org.freedesktop.MyIface") + .unwrap(); + let methods = iface.methods(); + for method in methods { + if method.name() != "TestSingleStructRet" && method.name() != "TestMultiRet" { + continue; + } + let args = method.args(); + let mut out_args = args .iter() - .find(|i| i.name() == "org.freedesktop.MyIface") - .unwrap(); - let methods = iface.methods(); - for method in methods { - if method.name() != "TestSingleStructRet" && method.name() != "TestMultiRet" { - continue; - } - let args = method.args(); - #[cfg(feature = "xml")] - let mut out_args = args - .iter() - .filter(|a| a.direction().unwrap() == zbus::xml::ArgDirection::Out); - - if method.name() == "TestSingleStructRet" { - assert_eq!(args.len(), 1); - assert_eq!(out_args.next().unwrap().ty().signature(), "(is)"); - assert!(out_args.next().is_none()); - } else { - assert_eq!(args.len(), 2); - let foo = out_args.find(|a| a.name() == Some("foo")).unwrap(); - assert_eq!(foo.ty().signature(), "i"); - let bar = out_args.find(|a| a.name() == Some("bar")).unwrap(); - assert_eq!(bar.ty().signature(), "s"); - } + .filter(|a| a.direction().unwrap() == zbus_xml::ArgDirection::Out); + + if method.name() == "TestSingleStructRet" { + assert_eq!(args.len(), 1); + assert_eq!(out_args.next().unwrap().ty().signature(), "(is)"); + assert!(out_args.next().is_none()); + } else { + assert_eq!(args.len(), 2); + let foo = out_args.find(|a| a.name() == Some("foo")).unwrap(); + assert_eq!(foo.ty().signature(), "i"); + let bar = out_args.find(|a| a.name() == Some("bar")).unwrap(); + assert_eq!(bar.ty().signature(), "s"); } } // build-time check to see if macro is doing the right thing. diff --git a/zbus_xml/Cargo.toml b/zbus_xml/Cargo.toml new file mode 100644 index 000000000..52f3826dd --- /dev/null +++ b/zbus_xml/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "zbus_xml" +version = "4.0.0" +authors = ["Zeeshan Ali Khan "] +edition = "2021" +rust-version = "1.64" + +description = "API to handle D-Bus introspection XML" +repository = "https://github.com/dbus2/zbus/" +keywords = ["D-Bus", "DBus", "IPC", "XML"] +license = "MIT" +categories = ["parsing"] +readme = "README.md" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +zvariant = { path = "../zvariant", version = "4.0.0", default-features = false } +zbus_names = { path = "../zbus_names", version = "3.0" } +quick-xml = { version = "0.27.1", features = ["serialize", "overlapped-lists"] } +static_assertions = "1.1.0" + +[dev-dependencies] +doc-comment = "0.3.3" + +[package.metadata.docs.rs] +all-features = true +targets = ["x86_64-unknown-linux-gnu"] diff --git a/zbus_xml/README.md b/zbus_xml/README.md new file mode 100644 index 000000000..9c25b0e5b --- /dev/null +++ b/zbus_xml/README.md @@ -0,0 +1,17 @@ +# zbus_xml + +[![](https://docs.rs/zbus_xml/badge.svg)](https://docs.rs/zbus_xml/) [![](https://img.shields.io/crates/v/zbus_xml)](https://crates.io/crates/zbus_xml) + +API to handle D-Bus introspection XML. + +Thanks to the [`org.freedesktop.DBus.Introspectable`] interface, objects may be introspected at +runtime, returning an XML string that describes the object. + +This crate provides facilities to parse the XML data into more convenient +Rust structures. The XML string may be parsed to a tree with [`Node::from_reader`]. + +**Status:** Stable. + +[`Node::from_reader`]: https://docs.rs/zbus_xml/latest/zbus_xml/struct.Node.html#method.from_reader +[Introspection format]: https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format +[`org.freedesktop.DBus.Introspectable`]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable diff --git a/zbus_xml/src/error.rs b/zbus_xml/src/error.rs new file mode 100644 index 000000000..a623064bf --- /dev/null +++ b/zbus_xml/src/error.rs @@ -0,0 +1,66 @@ +use quick_xml::de::DeError; +use static_assertions::assert_impl_all; +use std::{convert::Infallible, error, fmt}; +use zvariant::Error as VariantError; + +/// The error type for `zbus_names`. +/// +/// The various errors that can be reported by this crate. +#[derive(Clone, Debug)] +#[non_exhaustive] +pub enum Error { + Variant(VariantError), + /// An XML error from quick_xml + QuickXml(DeError), +} + +assert_impl_all!(Error: Send, Sync, Unpin); + +impl PartialEq for Error { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Variant(s), Self::Variant(o)) => s == o, + (Self::QuickXml(_), Self::QuickXml(_)) => false, + (_, _) => false, + } + } +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + Error::Variant(e) => Some(e), + Error::QuickXml(e) => Some(e), + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Variant(e) => write!(f, "{e}"), + Error::QuickXml(e) => write!(f, "XML error: {e}"), + } + } +} + +impl From for Error { + fn from(val: VariantError) -> Self { + Error::Variant(val) + } +} + +impl From for Error { + fn from(val: DeError) -> Self { + Error::QuickXml(val) + } +} + +impl From for Error { + fn from(i: Infallible) -> Self { + match i {} + } +} + +/// Alias for a `Result` with the error type `zbus_xml::Error`. +pub type Result = std::result::Result; diff --git a/zbus/src/xml.rs b/zbus_xml/src/lib.rs similarity index 87% rename from zbus/src/xml.rs rename to zbus_xml/src/lib.rs index bfe17ca25..2134832aa 100644 --- a/zbus/src/xml.rs +++ b/zbus_xml/src/lib.rs @@ -1,30 +1,25 @@ -//! Introspection XML support (`xml` feature) -//! -//! Thanks to the [`org.freedesktop.DBus.Introspectable`] interface, objects may be introspected at -//! runtime, returning an XML string that describes the object. -//! -//! This optional `xml` module provides facilities to parse the XML data into more convenient -//! Rust structures. The XML string may be parsed to a tree with [`Node.from_reader()`]. -//! -//! * [Introspection format] in the DBus specification -//! -//! [`Node.from_reader()`]: struct.Node.html#method.from_reader -//! [Introspection format]: https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format -//! [`org.freedesktop.DBus.Introspectable`]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable +#![deny(rust_2018_idioms)] +#![doc( + html_logo_url = "https://storage.googleapis.com/fdo-gitlab-uploads/project/avatar/3213/zbus-logomark.png" +)] +#![doc = include_str!("../README.md")] +#![doc(test(attr( + warn(unused), + deny(warnings), + // W/o this, we seem to get some bogus warning about `extern crate zbus`. + allow(unused_extern_crates), +)))] + +mod error; +pub use error::{Error, Result}; use quick_xml::{de::Deserializer, se::to_writer}; use serde::{Deserialize, Serialize}; use static_assertions::assert_impl_all; -use std::{ - io::{BufReader, Read, Write}, - result::Result, -}; +use std::io::{BufReader, Read, Write}; -use crate::{ - names::{InterfaceName, MemberName}, - zvariant::CompleteType, - Error, -}; +use zbus_names::{InterfaceName, MemberName}; +use zvariant::CompleteType; /// Annotations are generic key/value pairs of metadata. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] @@ -277,14 +272,14 @@ assert_impl_all!(Node<'_>: Send, Sync, Unpin); impl<'a> Node<'a> { /// Parse the introspection XML document from reader. - pub fn from_reader(reader: R) -> Result, Error> { + pub fn from_reader(reader: R) -> Result> { let mut deserializer = Deserializer::from_reader(BufReader::new(reader)); deserializer.event_buffer_size(Some(1024_usize.try_into().unwrap())); Ok(Node::deserialize(&mut deserializer)?) } /// Write the XML document to writer. - pub fn to_writer(&self, writer: W) -> Result<(), Error> { + pub fn to_writer(&self, writer: W) -> Result<()> { // Need this wrapper until this is resolved: https://github.com/tafia/quick-xml/issues/499 struct Writer(T); @@ -322,7 +317,7 @@ impl<'a> TryFrom<&'a str> for Node<'a> { type Error = Error; /// Parse the introspection XML document from `s`. - fn try_from(s: &'a str) -> Result, Error> { + fn try_from(s: &'a str) -> Result> { let mut deserializer = Deserializer::from_str(s); deserializer.event_buffer_size(Some(1024_usize.try_into().unwrap())); Ok(Node::deserialize(&mut deserializer)?) diff --git a/zbus/tests/data/invalid_arg_type.xml b/zbus_xml/tests/data/invalid_arg_type.xml similarity index 100% rename from zbus/tests/data/invalid_arg_type.xml rename to zbus_xml/tests/data/invalid_arg_type.xml diff --git a/zbus/tests/data/sample_object0.xml b/zbus_xml/tests/data/sample_object0.xml similarity index 100% rename from zbus/tests/data/sample_object0.xml rename to zbus_xml/tests/data/sample_object0.xml diff --git a/zbus/tests/xml.rs b/zbus_xml/tests/tests.xml similarity index 87% rename from zbus/tests/xml.rs rename to zbus_xml/tests/tests.xml index b8eb3b9cf..4e860f42b 100644 --- a/zbus/tests/xml.rs +++ b/zbus_xml/tests/tests.xml @@ -1,10 +1,7 @@ -#![cfg(feature = "xml")] - use quick_xml::de::DeError; use std::error::Error; -use test_log::test; -use zbus::xml::{ArgDirection, Node}; +use zbus_xml::{ArgDirection, Node}; #[test] fn serde() -> Result<(), Box> { @@ -36,6 +33,6 @@ fn invalid_arg_type() { let input = include_str!("data/invalid_arg_type.xml"); assert!(matches!( Node::try_from(input), - Err(zbus::Error::QuickXml(DeError::Custom(_))) + Err(zbus_xml::Error::QuickXml(DeError::Custom(_))) )); } diff --git a/zbus_xmlgen/Cargo.toml b/zbus_xmlgen/Cargo.toml index 6db018ee5..3e6221662 100644 --- a/zbus_xmlgen/Cargo.toml +++ b/zbus_xmlgen/Cargo.toml @@ -25,7 +25,8 @@ name = "zbus-xmlgen" path = "src/main.rs" [dependencies] -zbus = { path = "../zbus", version = "4.0.0", features = ["xml"] } +zbus = { path = "../zbus", version = "4.0.0" } +zbus_xml = { path = "../zbus_xml", version = "4.0.0" } zvariant = { path = "../zvariant", version = "4" } snakecase = "0.1.0" diff --git a/zbus_xmlgen/src/lib.rs b/zbus_xmlgen/src/lib.rs index a3a576859..87401217b 100644 --- a/zbus_xmlgen/src/lib.rs +++ b/zbus_xmlgen/src/lib.rs @@ -1,10 +1,8 @@ use snakecase::ascii::to_snakecase; use std::fmt::{Display, Formatter}; -use zbus::{ - names::BusName, - xml::{Arg, ArgDirection, Interface}, -}; +use zbus::names::BusName; +use zbus_xml::{Arg, ArgDirection, Interface}; use zvariant::{ Basic, CompleteType, ObjectPath, Signature, ARRAY_SIGNATURE_CHAR, DICT_ENTRY_SIG_END_CHAR, DICT_ENTRY_SIG_START_CHAR, STRUCT_SIG_END_CHAR, STRUCT_SIG_START_CHAR, VARIANT_SIGNATURE_CHAR, diff --git a/zbus_xmlgen/src/main.rs b/zbus_xmlgen/src/main.rs index 82eea707f..19827f1bd 100644 --- a/zbus_xmlgen/src/main.rs +++ b/zbus_xmlgen/src/main.rs @@ -13,8 +13,8 @@ use std::{ use zbus::{ blocking::{connection, fdo::IntrospectableProxy, Connection}, names::BusName, - xml::{Interface, Node}, }; +use zbus_xml::{Interface, Node}; use zbus_xmlgen::GenTrait; use zvariant::ObjectPath; diff --git a/zbus_xmlgen/tests/gen.rs b/zbus_xmlgen/tests/gen.rs index eade874cb..45d355974 100644 --- a/zbus_xmlgen/tests/gen.rs +++ b/zbus_xmlgen/tests/gen.rs @@ -1,7 +1,7 @@ use pretty_assertions::assert_eq; use std::{env, error::Error, io::Write, path::Path, result::Result}; -use zbus::xml::Node; +use zbus_xml::Node; use zbus_xmlgen::GenTrait; macro_rules! gen_diff {