use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
use zvariant::{OwnedValue, Value};
use crate::{Connection, Error, Message, Result};
use crate::fdo::{self, IntrospectableProxy, PropertiesProxy};
pub struct Proxy<'a> {
conn: Connection,
destination: Cow<'a, str>,
path: Cow<'a, str>,
interface: Cow<'a, str>,
}
impl<'a> Proxy<'a> {
pub fn new(
conn: &Connection,
destination: &'a str,
path: &'a str,
interface: &'a str,
) -> Result<Self> {
Ok(Self {
conn: conn.clone(),
destination: Cow::from(destination),
path: Cow::from(path),
interface: Cow::from(interface),
})
}
pub fn new_owned(
conn: Connection,
destination: String,
path: String,
interface: String,
) -> Result<Self> {
Ok(Self {
conn,
destination: Cow::from(destination),
path: Cow::from(path),
interface: Cow::from(interface),
})
}
pub fn introspect(&self) -> fdo::Result<String> {
IntrospectableProxy::new_for(&self.conn, &self.destination, &self.path)?.introspect()
}
pub fn get_property<T>(&self, property_name: &str) -> fdo::Result<T>
where
T: TryFrom<OwnedValue>,
{
PropertiesProxy::new_for(&self.conn, &self.destination, &self.path)?
.get(&self.interface, property_name)?
.try_into()
.map_err(|_| Error::InvalidReply.into())
}
pub fn set_property<'t, T: 't>(&self, property_name: &str, value: T) -> fdo::Result<()>
where
T: Into<Value<'t>>,
{
PropertiesProxy::new_for(&self.conn, &self.destination, &self.path)?.set(
&self.interface,
property_name,
&value.into(),
)
}
pub fn call_method<B>(&self, method_name: &str, body: &B) -> Result<Message>
where
B: serde::ser::Serialize + zvariant::Type,
{
let reply = self.conn.call_method(
Some(&self.destination),
&self.path,
Some(&self.interface),
method_name,
body,
);
match reply {
Ok(mut reply) => {
reply.disown_fds();
Ok(reply)
}
Err(e) => Err(e),
}
}
pub fn call<B, R>(&self, method_name: &str, body: &B) -> Result<R>
where
B: serde::ser::Serialize + zvariant::Type,
R: serde::de::DeserializeOwned + zvariant::Type,
{
Ok(self.call_method(method_name, body)?.body()?)
}
}