use std::{borrow::Cow, collections::HashMap};
#[cfg(feature = "service")]
use super::Error;
use super::Result;
#[cfg(feature = "service")]
use crate::{
BoxDBusError, Connection, ObjectServer, interface, message::Header,
object_server::SignalEmitter,
};
use crate::{OwnedVariant, Variant, names::InterfaceName};
#[cfg(feature = "service")]
pub struct Properties;
#[cfg(feature = "service")]
#[interface(name = "org.freedesktop.DBus.Properties", introspection_docs = false)]
impl Properties {
async fn get(
&self,
interface_name: InterfaceName<'_>,
property_name: &str,
#[zbus(connection)] conn: &Connection,
#[zbus(object_server)] server: &ObjectServer,
#[zbus(header)] header: Header<'_>,
#[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
) -> std::result::Result<OwnedVariant, BoxDBusError> {
let path = header.path().ok_or(crate::Error::MissingField)?;
let root = server.root().read().await;
let iface = root
.get_child(path)
.and_then(|node| node.interface_lock(interface_name.as_ref()))
.ok_or_else(|| {
Error::UnknownInterface(format!("Unknown interface '{interface_name}'"))
})?;
let res = iface
.instance
.read()
.await
.get(property_name, server, conn, Some(&header), &emitter)
.await;
res.unwrap_or_else(|| {
Err(Error::UnknownProperty(format!("Unknown property '{property_name}'")).into())
})
}
#[allow(clippy::too_many_arguments)]
async fn set(
&self,
interface_name: InterfaceName<'_>,
property_name: &str,
value: &Variant<'_>,
#[zbus(object_server)] server: &ObjectServer,
#[zbus(connection)] connection: &Connection,
#[zbus(header)] header: Header<'_>,
#[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
) -> std::result::Result<(), BoxDBusError> {
let path = header.path().ok_or(crate::Error::MissingField)?;
let root = server.root().read().await;
let iface = root
.get_child(path)
.and_then(|node| node.interface_lock(interface_name.as_ref()))
.ok_or_else(|| {
Error::UnknownInterface(format!("Unknown interface '{interface_name}'"))
})?;
match iface.instance.read().await.set(
property_name,
value,
server,
connection,
Some(&header),
&emitter,
) {
zbus::object_server::DispatchResult::RequiresMut => {}
zbus::object_server::DispatchResult::NotFound => {
return Err(
Error::UnknownProperty(format!("Unknown property '{property_name}'")).into(),
);
}
zbus::object_server::DispatchResult::Async(f) => {
return f.await;
}
}
let res = iface
.instance
.write()
.await
.set_mut(
property_name,
value,
server,
connection,
Some(&header),
&emitter,
)
.await;
res.unwrap_or_else(|| {
Err(Error::UnknownProperty(format!("Unknown property '{property_name}'")).into())
})
}
async fn get_all(
&self,
interface_name: InterfaceName<'_>,
#[zbus(object_server)] server: &ObjectServer,
#[zbus(connection)] connection: &Connection,
#[zbus(header)] header: Header<'_>,
#[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
) -> Result<HashMap<String, OwnedVariant>> {
let path = header.path().ok_or(crate::Error::MissingField)?;
let root = server.root().read().await;
let iface = root
.get_child(path)
.and_then(|node| node.interface_lock(interface_name.as_ref()))
.ok_or_else(|| {
Error::UnknownInterface(format!("Unknown interface '{interface_name}'"))
})?;
let res = iface
.instance
.read()
.await
.get_all(server, connection, Some(&header), &emitter)
.await?;
Ok(res)
}
#[zbus(signal)]
#[rustfmt::skip]
pub async fn properties_changed(
emitter: &SignalEmitter<'_>,
interface_name: InterfaceName<'_>,
changed_properties: HashMap<&str, Variant<'_>>,
invalidated_properties: Cow<'_, [&str]>,
) -> zbus::Result<()>;
}
#[cfg(feature = "proxy")]
#[crate::proxy(interface = "org.freedesktop.DBus.Properties")]
pub trait Properties {
fn get(&self, interface_name: InterfaceName<'_>, property_name: &str) -> Result<OwnedVariant>;
fn set(
&self,
interface_name: InterfaceName<'_>,
property_name: &str,
value: &Variant<'_>,
) -> Result<()>;
fn get_all(&self, interface_name: InterfaceName<'_>) -> Result<HashMap<String, OwnedVariant>>;
#[zbus(signal)]
fn properties_changed(
&self,
interface_name: InterfaceName<'_>,
changed_properties: HashMap<&str, Variant<'_>>,
invalidated_properties: Cow<'_, [&str]>,
) -> zbus::Result<()>;
}