use std::{
io::Read,
os::{fd::AsFd, unix::net::UnixStream},
};
use serde::Serialize;
use zbus::zvariant::{
Fd, Type,
as_value::{self, optional},
};
use super::{HandleToken, Request};
use crate::{Error, proxy::Proxy};
#[derive(Serialize, Type, Debug, Default)]
#[zvariant(signature = "dict")]
pub struct RetrieveOptions {
#[serde(with = "as_value")]
handle_token: HandleToken,
#[serde(with = "optional", skip_serializing_if = "Option::is_none")]
token: Option<String>,
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Secret")]
pub struct Secret(Proxy<'static>);
impl Secret {
pub async fn new() -> Result<Secret, Error> {
let proxy = Proxy::new_desktop("org.freedesktop.portal.Secret").await?;
Ok(Self(proxy))
}
pub async fn with_connection(connection: zbus::Connection) -> Result<Secret, Error> {
let proxy =
Proxy::new_desktop_with_connection(connection, "org.freedesktop.portal.Secret").await?;
Ok(Self(proxy))
}
pub fn version(&self) -> u32 {
self.0.version()
}
#[doc(alias = "RetrieveSecret")]
pub async fn retrieve(
&self,
fd: &impl AsFd,
options: RetrieveOptions,
) -> Result<Request<()>, Error> {
self.0
.empty_request(
&options.handle_token,
"RetrieveSecret",
&(Fd::from(fd), &options),
)
.await
}
}
impl std::ops::Deref for Secret {
type Target = zbus::Proxy<'static>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub async fn retrieve() -> Result<Vec<u8>, Error> {
let proxy = Secret::new().await?;
let (mut x1, x2) = UnixStream::pair()?;
proxy.retrieve(&x2, Default::default()).await?;
drop(x2);
#[cfg(feature = "tokio")]
let buf = tokio::task::spawn_blocking(move || {
let mut buf = Vec::with_capacity(64);
x1.read_to_end(&mut buf)?;
Ok::<_, std::io::Error>(buf)
})
.await
.map_err(|e| Error::from(std::io::Error::other(e)))??;
#[cfg(not(feature = "tokio"))]
let buf = {
let mut buf = Vec::with_capacity(64);
x1.read_to_end(&mut buf)?;
buf
};
Ok(buf)
}