mod dispatch_result;
pub use dispatch_result::*;
mod interface_ref;
pub use interface_ref::*;
mod interface_deref;
pub use interface_deref::*;
use std::{
any::Any,
collections::HashMap,
fmt::{self, Write},
sync::Arc,
};
use async_trait::async_trait;
use crate::{
BoxDBusError, Connection, DBusError, Error, ObjectServer, OwnedVariant, Variant, fdo,
message::{self, Header, Message},
names::{InterfaceName, MemberName},
object_server::SignalEmitter,
runtime::locks::RwLock,
};
#[doc(hidden)]
pub fn introspect_doc_comment(writer: &mut dyn Write, level: usize, lines: &str) {
writeln!(writer, "{:indent$}<!--", "", indent = level).unwrap();
for line in lines.split('\n') {
if line.is_empty() {
writeln!(writer).unwrap();
} else {
writeln!(writer, "{:indent$}{line}", "", indent = level).unwrap();
}
}
writeln!(writer, "{:indent$} -->", "", indent = level).unwrap();
}
#[async_trait]
pub trait Interface: Any + Send + Sync {
fn name() -> InterfaceName<'static>
where
Self: Sized;
fn spawn_tasks_for_methods(&self) -> bool {
true
}
async fn get(
&self,
property_name: &str,
server: &ObjectServer,
connection: &Connection,
header: Option<&message::Header<'_>>,
emitter: &SignalEmitter<'_>,
) -> Option<Result<OwnedVariant, BoxDBusError>>;
async fn get_all(
&self,
object_server: &ObjectServer,
connection: &Connection,
header: Option<&message::Header<'_>>,
emitter: &SignalEmitter<'_>,
) -> fdo::Result<HashMap<String, OwnedVariant>>;
fn set<'call>(
&'call self,
property_name: &'call str,
value: &'call Variant<'_>,
object_server: &'call ObjectServer,
connection: &'call Connection,
header: Option<&'call message::Header<'_>>,
emitter: &'call SignalEmitter<'_>,
) -> DispatchResult<'call> {
let _ = (
property_name,
value,
object_server,
connection,
header,
emitter,
);
DispatchResult::RequiresMut
}
async fn set_mut(
&mut self,
property_name: &str,
value: &Variant<'_>,
object_server: &ObjectServer,
connection: &Connection,
header: Option<&Header<'_>>,
emitter: &SignalEmitter<'_>,
) -> Option<Result<(), BoxDBusError>>;
fn call<'call>(
&'call self,
server: &'call ObjectServer,
connection: &'call Connection,
msg: &'call Message,
name: MemberName<'call>,
) -> DispatchResult<'call>;
fn call_mut<'call>(
&'call mut self,
server: &'call ObjectServer,
connection: &'call Connection,
msg: &'call Message,
name: MemberName<'call>,
) -> DispatchResult<'call>;
fn introspect_to_writer(&self, writer: &mut dyn Write, level: usize);
}
#[doc(hidden)]
pub trait IntoDBusError {
fn into_dbus_error(self) -> BoxDBusError;
fn into_error(self) -> Error;
}
impl<E> IntoDBusError for E
where
E: DBusError + Send + Sync + 'static,
{
fn into_dbus_error(self) -> BoxDBusError {
Box::new(self)
}
fn into_error(self) -> Error {
Error::DBus(Arc::new(self))
}
}
impl IntoDBusError for Error {
fn into_dbus_error(self) -> BoxDBusError {
self.into()
}
fn into_error(self) -> Error {
self
}
}
#[derive(Clone)]
pub(crate) struct ArcInterface {
pub instance: Arc<RwLock<dyn Interface>>,
pub spawn_tasks_for_methods: bool,
}
impl ArcInterface {
pub fn new<I>(iface: I) -> Self
where
I: Interface,
{
let spawn_tasks_for_methods = iface.spawn_tasks_for_methods();
Self {
instance: Arc::new(RwLock::new(iface)),
spawn_tasks_for_methods,
}
}
}
impl fmt::Debug for ArcInterface {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Arc<RwLock<dyn Interface>>")
.finish_non_exhaustive()
}
}