#![deny(rust_2018_idioms)]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/dbus2/zbus/9f7a90d2b594ddc48b7a5f39fda5e00cd56a7dfb/logo.png"
)]
#![doc = include_str!("../README.md")]
#![doc(test(attr(
warn(unused),
deny(warnings),
allow(dead_code),
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},
ops::Deref,
};
use zbus_names::{InterfaceName, MemberName, PropertyName};
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Annotation {
#[serde(rename = "@name")]
name: String,
#[serde(rename = "@value")]
value: String,
}
assert_impl_all!(Annotation: Send, Sync, Unpin);
impl Annotation {
pub fn name(&self) -> &str {
&self.name
}
pub fn value(&self) -> &str {
&self.value
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum ArgDirection {
#[serde(rename = "in")]
In,
#[serde(rename = "out")]
Out,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct Arg {
#[serde(rename = "@name")]
name: Option<String>,
#[serde(rename = "@type")]
ty: Signature,
#[serde(rename = "@direction")]
direction: Option<ArgDirection>,
#[serde(rename = "annotation", default)]
annotations: Vec<Annotation>,
}
assert_impl_all!(Arg: Send, Sync, Unpin);
impl Arg {
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub fn ty(&self) -> &Signature {
&self.ty
}
pub fn direction(&self) -> Option<ArgDirection> {
self.direction
}
pub fn annotations(&self) -> &[Annotation] {
&self.annotations
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct Method<'a> {
#[serde(rename = "@name", borrow)]
name: MemberName<'a>,
#[serde(rename = "arg", default)]
args: Vec<Arg>,
#[serde(rename = "annotation", default)]
annotations: Vec<Annotation>,
}
assert_impl_all!(Method<'_>: Send, Sync, Unpin);
impl<'a> Method<'a> {
pub fn name(&self) -> MemberName<'_> {
self.name.as_ref()
}
pub fn args(&self) -> &[Arg] {
&self.args
}
pub fn annotations(&self) -> &[Annotation] {
&self.annotations
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct Signal<'a> {
#[serde(rename = "@name", borrow)]
name: MemberName<'a>,
#[serde(rename = "arg", default)]
args: Vec<Arg>,
#[serde(rename = "annotation", default)]
annotations: Vec<Annotation>,
}
assert_impl_all!(Signal<'_>: Send, Sync, Unpin);
impl<'a> Signal<'a> {
pub fn name(&self) -> MemberName<'_> {
self.name.as_ref()
}
pub fn args(&self) -> &[Arg] {
&self.args
}
pub fn annotations(&self) -> &[Annotation] {
&self.annotations
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PropertyAccess {
#[serde(rename = "read")]
Read,
#[serde(rename = "write")]
Write,
#[serde(rename = "readwrite")]
ReadWrite,
}
impl PropertyAccess {
pub fn read(&self) -> bool {
matches!(self, PropertyAccess::Read | PropertyAccess::ReadWrite)
}
pub fn write(&self) -> bool {
matches!(self, PropertyAccess::Write | PropertyAccess::ReadWrite)
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct Property<'a> {
#[serde(rename = "@name", borrow)]
name: PropertyName<'a>,
#[serde(rename = "@type")]
ty: Signature,
#[serde(rename = "@access")]
access: PropertyAccess,
#[serde(rename = "annotation", default)]
annotations: Vec<Annotation>,
}
assert_impl_all!(Property<'_>: Send, Sync, Unpin);
impl<'a> Property<'a> {
pub fn name(&self) -> PropertyName<'_> {
self.name.as_ref()
}
pub fn ty(&self) -> &Signature {
&self.ty
}
pub fn access(&self) -> PropertyAccess {
self.access
}
pub fn annotations(&self) -> &[Annotation] {
&self.annotations
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct Interface<'a> {
#[serde(rename = "@name", borrow)]
name: InterfaceName<'a>,
#[serde(rename = "method", default)]
methods: Vec<Method<'a>>,
#[serde(rename = "property", default)]
properties: Vec<Property<'a>>,
#[serde(rename = "signal", default)]
signals: Vec<Signal<'a>>,
#[serde(rename = "annotation", default)]
annotations: Vec<Annotation>,
}
assert_impl_all!(Interface<'_>: Send, Sync, Unpin);
impl<'a> Interface<'a> {
pub fn name(&self) -> InterfaceName<'_> {
self.name.as_ref()
}
pub fn methods(&self) -> &[Method<'a>] {
&self.methods
}
pub fn signals(&self) -> &[Signal<'a>] {
&self.signals
}
pub fn properties(&self) -> &[Property<'_>] {
&self.properties
}
pub fn annotations(&self) -> &[Annotation] {
&self.annotations
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct Node<'a> {
#[serde(rename = "@name")]
name: Option<String>,
#[serde(rename = "interface", default, borrow)]
interfaces: Vec<Interface<'a>>,
#[serde(rename = "node", default, borrow)]
nodes: Vec<Node<'a>>,
}
assert_impl_all!(Node<'_>: Send, Sync, Unpin);
impl<'a> Node<'a> {
pub fn from_reader<R: Read>(reader: R) -> Result<Node<'a>> {
let mut deserializer = Deserializer::from_reader(BufReader::new(reader));
deserializer.event_buffer_size(Some(1024_usize.try_into().unwrap()));
Ok(Node::deserialize(&mut deserializer)?)
}
pub fn to_writer<W: Write>(&self, writer: W) -> Result<()> {
struct Writer<T>(T);
impl<T> std::fmt::Write for Writer<T>
where
T: Write,
{
fn write_str(&mut self, s: &str) -> std::fmt::Result {
self.0.write_all(s.as_bytes()).map_err(|_| std::fmt::Error)
}
}
to_writer(Writer(writer), &self)?;
Ok(())
}
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub fn nodes(&self) -> &[Node<'a>] {
&self.nodes
}
pub fn interfaces(&self) -> &[Interface<'a>] {
&self.interfaces
}
}
impl<'a> TryFrom<&'a str> for Node<'a> {
type Error = Error;
fn try_from(s: &'a str) -> Result<Node<'a>> {
let mut deserializer = Deserializer::from_str(s);
deserializer.event_buffer_size(Some(1024_usize.try_into().unwrap()));
Ok(Node::deserialize(&mut deserializer)?)
}
}
#[derive(Debug, Serialize, Clone, PartialEq)]
pub struct Signature(zvariant::Signature);
impl Signature {
pub fn inner(&self) -> &zvariant::Signature {
&self.0
}
pub fn into_inner(self) -> zvariant::Signature {
self.0
}
}
impl<'de> serde::de::Deserialize<'de> for Signature {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
String::deserialize(deserializer).and_then(|s| {
zvariant::Signature::try_from(s.as_bytes())
.map_err(serde::de::Error::custom)
.map(Signature)
})
}
}
impl Deref for Signature {
type Target = zvariant::Signature;
fn deref(&self) -> &Self::Target {
self.inner()
}
}
impl PartialEq<str> for Signature {
fn eq(&self, other: &str) -> bool {
self.0 == other
}
}