1use std::{borrow::Cow, collections::HashMap};
7use zbus_names::InterfaceName;
8use zvariant::{OwnedValue, Value};
9
10use super::{Error, Result};
11use crate::{interface, message::Header, object_server::SignalEmitter, Connection, ObjectServer};
12
13pub struct Properties;
17
18#[interface(
19 name = "org.freedesktop.DBus.Properties",
20 introspection_docs = false,
21 proxy(visibility = "pub")
22)]
23impl Properties {
24 async fn get(
26 &self,
27 interface_name: InterfaceName<'_>,
28 property_name: &str,
29 #[zbus(connection)] conn: &Connection,
30 #[zbus(object_server)] server: &ObjectServer,
31 #[zbus(header)] header: Header<'_>,
32 #[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
33 ) -> Result<OwnedValue> {
34 let path = header.path().ok_or(crate::Error::MissingField)?;
35 let root = server.root().read().await;
36 let iface = root
37 .get_child(path)
38 .and_then(|node| node.interface_lock(interface_name.as_ref()))
39 .ok_or_else(|| {
40 Error::UnknownInterface(format!("Unknown interface '{interface_name}'"))
41 })?;
42
43 let res = iface
44 .instance
45 .read()
46 .await
47 .get(property_name, server, conn, Some(&header), &emitter)
48 .await;
49 res.unwrap_or_else(|| {
50 Err(Error::UnknownProperty(format!(
51 "Unknown property '{property_name}'"
52 )))
53 })
54 }
55
56 #[allow(clippy::too_many_arguments)]
58 async fn set(
59 &self,
60 interface_name: InterfaceName<'_>,
61 property_name: &str,
62 value: Value<'_>,
63 #[zbus(object_server)] server: &ObjectServer,
64 #[zbus(connection)] connection: &Connection,
65 #[zbus(header)] header: Header<'_>,
66 #[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
67 ) -> Result<()> {
68 let path = header.path().ok_or(crate::Error::MissingField)?;
69 let root = server.root().read().await;
70 let iface = root
71 .get_child(path)
72 .and_then(|node| node.interface_lock(interface_name.as_ref()))
73 .ok_or_else(|| {
74 Error::UnknownInterface(format!("Unknown interface '{interface_name}'"))
75 })?;
76
77 match iface.instance.read().await.set(
78 property_name,
79 &value,
80 server,
81 connection,
82 Some(&header),
83 &emitter,
84 ) {
85 zbus::object_server::DispatchResult::RequiresMut => {}
86 zbus::object_server::DispatchResult::NotFound => {
87 return Err(Error::UnknownProperty(format!(
88 "Unknown property '{property_name}'"
89 )));
90 }
91 zbus::object_server::DispatchResult::Async(f) => {
92 return f.await.map_err(Into::into);
93 }
94 }
95 let res = iface
96 .instance
97 .write()
98 .await
99 .set_mut(
100 property_name,
101 &value,
102 server,
103 connection,
104 Some(&header),
105 &emitter,
106 )
107 .await;
108 res.unwrap_or_else(|| {
109 Err(Error::UnknownProperty(format!(
110 "Unknown property '{property_name}'"
111 )))
112 })
113 }
114
115 async fn get_all(
117 &self,
118 interface_name: InterfaceName<'_>,
119 #[zbus(object_server)] server: &ObjectServer,
120 #[zbus(connection)] connection: &Connection,
121 #[zbus(header)] header: Header<'_>,
122 #[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
123 ) -> Result<HashMap<String, OwnedValue>> {
124 let path = header.path().ok_or(crate::Error::MissingField)?;
125 let root = server.root().read().await;
126 let iface = root
127 .get_child(path)
128 .and_then(|node| node.interface_lock(interface_name.as_ref()))
129 .ok_or_else(|| {
130 Error::UnknownInterface(format!("Unknown interface '{interface_name}'"))
131 })?;
132
133 let res = iface
134 .instance
135 .read()
136 .await
137 .get_all(server, connection, Some(&header), &emitter)
138 .await?;
139 Ok(res)
140 }
141
142 #[zbus(signal)]
144 #[rustfmt::skip]
145 pub async fn properties_changed(
146 emitter: &SignalEmitter<'_>,
147 interface_name: InterfaceName<'_>,
148 changed_properties: HashMap<&str, Value<'_>>,
149 invalidated_properties: Cow<'_, [&str]>,
150 ) -> zbus::Result<()>;
151}