pub(crate) const DESTINATION: &str = "org.freedesktop.portal.Documents";
pub(crate) const PATH: &str = "/org/freedesktop/portal/documents";
use crate::{helpers::call_method, Error};
use enumflags2::BitFlags;
use serde::{de::Deserializer, Deserialize, Serialize, Serializer};
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::{collections::HashMap, os::unix::prelude::AsRawFd};
use std::{fmt::Debug, str::FromStr};
use strum_macros::{AsRefStr, EnumString, IntoStaticStr, ToString};
use zvariant::{Fd, Signature};
use zvariant_derive::Type;
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Copy, Clone, BitFlags, Debug, Type)]
#[repr(u32)]
pub enum Flags {
ReuseExisting = 1,
Persistent = 2,
AsNeededByApp = 4,
ExportDirectory = 8,
}
pub type Permissions = HashMap<String, Vec<Permission>>;
#[derive(Debug, Clone, AsRefStr, EnumString, IntoStaticStr, ToString, PartialEq, Eq)]
#[strum(serialize_all = "lowercase")]
pub enum Permission {
Read,
Write,
#[strum(serialize = "grant-permissions")]
GrantPermissions,
Delete,
}
impl zvariant::Type for Permission {
fn signature() -> Signature<'static> {
String::signature()
}
}
impl Serialize for Permission {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
String::serialize(&self.to_string(), serializer)
}
}
impl<'de> Deserialize<'de> for Permission {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Permission::from_str(&String::deserialize(deserializer)?).expect("invalid permission"))
}
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Documents")]
pub struct DocumentsProxy<'a>(zbus::azync::Proxy<'a>);
impl<'a> DocumentsProxy<'a> {
pub async fn new(connection: &zbus::azync::Connection) -> Result<DocumentsProxy<'a>, Error> {
let proxy = zbus::ProxyBuilder::new_bare(connection)
.interface("org.freedesktop.portal.Documents")
.path(PATH)?
.destination(DESTINATION)
.build_async()
.await?;
Ok(Self(proxy))
}
pub fn inner(&self) -> &zbus::azync::Proxy<'_> {
&self.0
}
#[doc(alias = "Add")]
pub async fn add<F>(
&self,
o_path_fd: &F,
reuse_existing: bool,
persistent: bool,
) -> Result<String, Error>
where
F: AsRawFd + Debug,
{
call_method(
&self.0,
"Add",
&(Fd::from(o_path_fd.as_raw_fd()), reuse_existing, persistent),
)
.await
}
#[doc(alias = "AddFull")]
pub async fn add_full<F: AsRawFd>(
&self,
o_path_fds: &[&F],
flags: BitFlags<Flags>,
app_id: &str,
permissions: &[Permission],
) -> Result<(Vec<String>, HashMap<String, zvariant::OwnedValue>), Error> {
let o_path: Vec<Fd> = o_path_fds.iter().map(|f| Fd::from(f.as_raw_fd())).collect();
call_method(&self.0, "AddFull", &(o_path, flags, app_id, permissions)).await
}
#[doc(alias = "AddNamed")]
pub async fn add_named<F>(
&self,
o_path_parent_fd: &F,
filename: &str,
reuse_existing: bool,
persistent: bool,
) -> Result<String, Error>
where
F: AsRawFd + Debug,
{
call_method(
&self.0,
"AddNamed",
&(
Fd::from(o_path_parent_fd.as_raw_fd()),
filename,
reuse_existing,
persistent,
),
)
.await
}
#[doc(alias = "AddNamedFull")]
pub async fn add_named_full<F>(
&self,
o_path_fd: &F,
filename: &str,
flags: BitFlags<Flags>,
app_id: &str,
permissions: &[Permission],
) -> Result<(String, HashMap<String, zvariant::OwnedValue>), Error>
where
F: AsRawFd + Debug,
{
call_method(
&self.0,
"AddNamedFull",
&(
Fd::from(o_path_fd.as_raw_fd()),
filename,
flags,
app_id,
permissions,
),
)
.await
}
#[doc(alias = "Delete")]
pub async fn delete(&self, doc_id: &str) -> Result<(), Error> {
call_method(&self.0, "Delete", &(doc_id)).await
}
#[doc(alias = "GetMountPoint")]
#[doc(alias = "get_mount_point")]
pub async fn mount_point(&self) -> Result<String, Error> {
call_method(&self.0, "GetMountPoint", &()).await
}
#[doc(alias = "GrantPermissions")]
pub async fn grant_permissions(
&self,
doc_id: &str,
app_id: &str,
permissions: &[Permission],
) -> Result<(), Error> {
call_method(&self.0, "GrantPermissions", &(doc_id, app_id, permissions)).await
}
#[doc(alias = "Info")]
pub async fn info(&self, doc_id: &str) -> Result<(String, Permissions), Error> {
call_method(&self.0, "Info", &(doc_id)).await
}
#[doc(alias = "List")]
pub async fn list(&self, app_id: &str) -> Result<HashMap<String, String>, Error> {
call_method(&self.0, "List", &(app_id)).await
}
#[doc(alias = "Lookup")]
pub async fn lookup(&self, filename: &str) -> Result<Option<String>, Error> {
let doc_id: String = call_method(&self.0, "Lookup", &(filename)).await?;
if doc_id.is_empty() {
Ok(None)
} else {
Ok(Some(doc_id))
}
}
#[doc(alias = "RevokePermissions")]
pub async fn revoke_permissions(
&self,
doc_id: &str,
app_id: &str,
permissions: &[Permission],
) -> Result<(), Error> {
call_method(&self.0, "RevokePermissions", &(doc_id, app_id, permissions)).await
}
}
mod file_transfer;
pub use file_transfer::FileTransferProxy;