From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- third_party/rust/dbus/src/crossroads/crossroads.rs | 245 +++++++++++++++++++++ third_party/rust/dbus/src/crossroads/handlers.rs | 138 ++++++++++++ third_party/rust/dbus/src/crossroads/info.rs | 220 ++++++++++++++++++ third_party/rust/dbus/src/crossroads/mod.rs | 15 ++ third_party/rust/dbus/src/crossroads/stdimpl.rs | 53 +++++ 5 files changed, 671 insertions(+) create mode 100644 third_party/rust/dbus/src/crossroads/crossroads.rs create mode 100644 third_party/rust/dbus/src/crossroads/handlers.rs create mode 100644 third_party/rust/dbus/src/crossroads/info.rs create mode 100644 third_party/rust/dbus/src/crossroads/mod.rs create mode 100644 third_party/rust/dbus/src/crossroads/stdimpl.rs (limited to 'third_party/rust/dbus/src/crossroads') diff --git a/third_party/rust/dbus/src/crossroads/crossroads.rs b/third_party/rust/dbus/src/crossroads/crossroads.rs new file mode 100644 index 0000000000..a856a6597c --- /dev/null +++ b/third_party/rust/dbus/src/crossroads/crossroads.rs @@ -0,0 +1,245 @@ +use std::collections::BTreeMap; +use std::any::{TypeId, Any}; +use std::ffi::{CString, CStr}; +use std::fmt; +use crate::{Path as PathName, Interface as IfaceName, Member as MemberName, Signature, Message, MessageType}; +use super::info::{IfaceInfo, MethodInfo, PropInfo, IfaceInfoBuilder}; +use super::handlers::{Handlers, Par, ParInfo, Mut, MutCtx, MutMethods}; +use super::stdimpl::DBusProperties; + +// The key is an IfaceName, but if we have that we bump into https://github.com/rust-lang/rust/issues/59732 +// so we use CString as a workaround. +#[derive(Default, Debug)] +struct IfaceReg(BTreeMap)>); + +#[derive(Default)] +pub struct PathData(Vec<(TypeId, H::Iface)>); + +impl PathData { + pub fn insert_par(&mut self, i: I) { + let id = TypeId::of::(); + let t = Box::new(i); + self.0.push((id, t)); + } +} + +impl PathData { + pub fn insert_mut(&mut self, i: I) { + let id = TypeId::of::(); + let t = Box::new(i); + self.0.push((id, t)); + } +} + +impl fmt::Debug for PathData { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "...") } +} + +impl PathData { + fn new() -> Self { PathData(vec!()) } +} + +#[derive(Debug)] +struct IfacePaths(BTreeMap>); + +impl Default for IfacePaths { + fn default() -> Self { IfacePaths(BTreeMap::new()) } +} + +struct MsgHeaders<'a> { + m: MemberName<'a>, + i: IfaceName<'a>, + p: PathName<'a>, +} + +fn msg_headers(msg: &Message) -> Option { + if msg.msg_type() != MessageType::MethodCall { return None }; + let p = msg.path()?; + let i = msg.interface()?; + let m = msg.member()?; + Some(MsgHeaders { m, i, p }) +} + +#[derive(Debug)] +pub (super) struct MLookup<'a, H: Handlers> { + pub (super) cr: &'a Crossroads, + pub (super) data: &'a PathData, + pub (super) iface: &'a H::Iface, + pub (super) iinfo: &'a IfaceInfo<'static, H>, +// pub (super) minfo: Option<&'a MethodInfo<'static, H>>, +// pub (super) pinfo: Option<&'a PropInfo<'static, H>>, +} + +#[derive(Debug)] +pub struct Crossroads { + reg: IfaceReg, + paths: IfacePaths, +} + +impl Crossroads { + + pub fn register_custom(&mut self, info: IfaceInfo<'static, H>) -> Option> { + self.reg.0.insert(info.name.clone().into_cstring(), (TypeId::of::(), info)).map(|x| x.1) + } + pub fn insert>>(&mut self, name: N, data: PathData) { + self.paths.0.insert(name.into().into_cstring(), data); + } + pub fn get_data>>(&self, name: N) -> Option<&PathData> { + self.paths.0.get(name.into().as_cstr()) + } + + pub fn register<'a, I: 'static, N: Into>>(&'a mut self, name: N) -> IfaceInfoBuilder<'a, I, H> { + IfaceInfoBuilder::new(Some(self), name.into()) + } + + fn reg_lookup(&self, headers: &MsgHeaders) -> Option<(MLookup, &MethodInfo<'static, H>)> { + let (typeid, iinfo) = self.reg.0.get(headers.i.as_cstr())?; + let minfo = iinfo.methods.iter().find(|x| x.name() == &headers.m)?; + let data = self.paths.0.get(headers.p.as_cstr())?; + let (_, iface) = data.0.iter().find(|x| x.0 == *typeid)?; + Some((MLookup { cr: self, data, iface, iinfo }, minfo)) + } + + pub (super) fn reg_prop_lookup<'a>(&'a self, data: &'a PathData, iname: &CStr, propname: &CStr) -> + Option<(MLookup<'a, H>, &PropInfo<'static, H>)> { + let (typeid, iinfo) = self.reg.0.get(iname)?; + let pinfo = iinfo.props.iter().find(|x| x.name.as_cstr() == propname)?; + let (_, iface) = data.0.iter().find(|x| x.0 == *typeid)?; + Some((MLookup { cr: self, data, iface, iinfo}, pinfo)) + } +} + +impl Crossroads { + pub fn dispatch_par(&self, msg: &Message) -> Option> { + let headers = msg_headers(msg)?; + let (lookup, minfo) = self.reg_lookup(&headers)?; + let handler = minfo.handler(); + let iface = &**lookup.iface; + let mut info = ParInfo::new(msg, lookup); + let r = (handler)(iface, &mut info); + Some(r.into_iter().collect()) + } + + pub fn new_par() -> Self { + let mut cr = Crossroads { + reg: IfaceReg(BTreeMap::new()), + paths: IfacePaths(BTreeMap::new()), + }; + DBusProperties::register(&mut cr); + cr + } +} + +impl Crossroads { + pub fn dispatch_mut(&mut self, msg: &Message) -> Option> { + let headers = msg_headers(msg)?; + let (typeid, iinfo) = self.reg.0.get_mut(headers.i.as_cstr())?; + let minfo = iinfo.methods.iter_mut().find(|x| x.name() == &headers.m)?; + let ctx = MutCtx::new(msg); + let r = match minfo.handler_mut().0 { + MutMethods::MutIface(ref mut f) => { + let data = self.paths.0.get_mut(headers.p.as_cstr())?; + let (_, iface) = data.0.iter_mut().find(|x| x.0 == *typeid)?; + let iface = &mut **iface; + f(iface, &ctx) + } + }; + Some(r.into_iter().collect()) + } + + pub fn new_mut() -> Self { + let cr = Crossroads { + reg: IfaceReg(BTreeMap::new()), + paths: IfacePaths(BTreeMap::new()), + }; + // DBusProperties::register(&mut cr); + cr + } +} + + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_send_sync() { + fn is_send(_: &T) {} + fn is_sync(_: &T) {} + let c = Crossroads::new_par(); + dbg!(&c); + is_send(&c); + is_sync(&c); + } + + #[test] + fn cr_mut() { + let mut cr = Crossroads::new_mut(); + + struct Score(u16); + + let mut call_times = 0u32; + cr.register::("com.example.dbusrs.crossroads.score") + .method_iface("UpdateScore", ("change",), ("new_score", "call_times"), move |score, _, (change,): (u16,)| { + score.0 += change; + call_times += 1; + Ok((score.0, call_times)) + }); + + let mut pdata = PathData::new(); + pdata.insert_mut(Score(7u16)); + cr.insert("/", pdata); + + let msg = Message::new_method_call("com.example.dbusrs.crossroads.score", "/", "com.example.dbusrs.crossroads.score", "UpdateScore").unwrap(); + let mut msg = msg.append1(5u16); + crate::message::message_set_serial(&mut msg, 57); + let mut r = cr.dispatch_mut(&msg).unwrap(); + assert_eq!(r.len(), 1); + r[0].as_result().unwrap(); + let (new_score, call_times): (u16, u32) = r[0].read2().unwrap(); + assert_eq!(new_score, 12); + assert_eq!(call_times, 1); + } + + + #[test] + fn cr_par() { + let mut cr = Crossroads::new_par(); + + struct Score(u16); + + cr.register::("com.example.dbusrs.crossroads.score") + .method("Hello", ("sender",), ("reply",), |score, _, (sender,): (String,)| { + assert_eq!(score.0, 7u16); + Ok((format!("Hello {}, my score is {}!", sender, score.0),)) + }) + .prop_ro("Score", |score, _| { + assert_eq!(score.0, 7u16); + Ok(score.0) + }) + .signal::<(u16,),_>("ScoreChanged", ("NewScore",)); + + let mut pdata = PathData::new(); + pdata.insert_par(Score(7u16)); + pdata.insert_par(DBusProperties); + cr.insert("/", pdata); + + let msg = Message::new_method_call("com.example.dbusrs.crossroads.score", "/", "com.example.dbusrs.crossroads.score", "Hello").unwrap(); + let mut msg = msg.append1("example"); + crate::message::message_set_serial(&mut msg, 57); + let mut r = cr.dispatch_par(&msg).unwrap(); + assert_eq!(r.len(), 1); + r[0].as_result().unwrap(); + let rr: String = r[0].read1().unwrap(); + assert_eq!(&rr, "Hello example, my score is 7!"); + + let msg = Message::new_method_call("com.example.dbusrs.crossroads.score", "/", "org.freedesktop.DBus.Properties", "Get").unwrap(); + let mut msg = msg.append2("com.example.dbusrs.crossroads.score", "Score"); + crate::message::message_set_serial(&mut msg, 57); + let mut r = cr.dispatch_par(&msg).unwrap(); + assert_eq!(r.len(), 1); + r[0].as_result().unwrap(); + let z: u16 = r[0].read1().unwrap(); + assert_eq!(z, 7u16); + } +} diff --git a/third_party/rust/dbus/src/crossroads/handlers.rs b/third_party/rust/dbus/src/crossroads/handlers.rs new file mode 100644 index 0000000000..2d466ba119 --- /dev/null +++ b/third_party/rust/dbus/src/crossroads/handlers.rs @@ -0,0 +1,138 @@ +use std::{fmt, cell}; +use std::any::Any; +use crate::arg::ArgBuilder; +use crate::{Path as PathName, Interface as IfaceName, Member as MemberName, Signature, Message, arg}; +use super::crossroads::{Crossroads, PathData, MLookup}; +use super::info::{MethodInfo, PropInfo}; +use super::MethodErr; + +pub struct DebugMethod(pub H::Method); +impl fmt::Debug for DebugMethod { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "...") } +} + +pub struct DebugProp(pub Option, pub Option); +impl fmt::Debug for DebugProp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "...") } +} + +pub trait Handlers { + type Method; + type GetProp; + type SetProp; + type Iface; +} + +/// Parallel tree - Par +#[derive(Debug, Clone, Copy, Default)] +pub struct Par; + +impl Par { + pub fn typed_getprop(getf: G) -> ::GetProp + where G: Fn(&I, &ParInfo) -> Result + Send + Sync + 'static { + Box::new(move |data, ia, info| { + let iface: &I = data.downcast_ref().unwrap(); + let t = getf(iface, info)?; + ia.append(t); + Ok(()) + }) + } + + pub fn typed_setprop arg::Get<'z>, S>(setf: S) -> ::SetProp + where S: Fn(&I, &ParInfo, T) -> Result<(), MethodErr> + Send + Sync + 'static { + Box::new(move |data, ii, info| { + let iface: &I = data.downcast_ref().unwrap(); + let t: T = ii.read()?; + setf(iface, info, t) + }) + } +} + +#[derive(Debug)] +pub struct ParInfo<'a> { + lookup: MLookup<'a, Par>, + message: &'a Message, +} + +impl<'a> ParInfo<'a> { + pub fn msg(&self) -> &Message { self.message } + pub (super) fn new(msg: &'a Message, lookup: MLookup<'a, Par>) -> Self { + ParInfo { lookup, message: msg } + } + pub fn path_data(&self) -> &PathData { self.lookup.data } + pub fn crossroads(&self) -> &Crossroads { self.lookup.cr } +} + +impl Handlers for Par { + type Method = Box Option + Send + Sync + 'static>; + type GetProp = Box Result<(), MethodErr> + Send + Sync + 'static>; + type SetProp = Box Result<(), MethodErr> + Send + Sync + 'static>; + type Iface = Box; +} + +impl MethodInfo<'_, Par> { + pub fn new_par(name: N, f: F) -> Self where + F: Fn(&T, &ParInfo) -> Result, MethodErr> + Send + Sync + 'static, + N: Into>, + T: Any + Send + Sync + 'static, + { + Self::new(name.into(), Box::new(move |data, info| { + let x = data.downcast_ref().unwrap(); + f(x, info).unwrap_or_else(|e| { Some(e.to_message(info.message)) }) + })) + } +} + + +/// Mutable, non-Send tree +#[derive(Debug, Clone, Copy, Default)] +pub struct Mut; + +#[derive(Debug)] +pub struct MutCtx<'a> { + message: &'a Message, + send_extra: cell::RefCell>, +} + +impl<'a> MutCtx<'a> { + pub fn msg(&self) -> &Message { self.message } + pub fn send(&self, msg: Message) { self.send_extra.borrow_mut().push(msg); } + pub (super) fn new(msg: &'a Message) -> Self { MutCtx { message: msg, send_extra: Default::default() } } +} + +impl Handlers for Mut { + type Method = MutMethod; + type GetProp = Box Result<(), MethodErr> + 'static>; + type SetProp = Box Result<(), MethodErr> + 'static>; + type Iface = Box; +} + + +pub struct MutMethod(pub (super) MutMethods); + +pub (super) enum MutMethods { + MutIface(Box Option + 'static>), +// Info(Box Option + 'static>), +// MutCr(fn(&mut Crossroads, &Message) -> Vec), +} + +impl Mut { + pub fn typed_method_iface(mut f: F) -> ::Method + where F: FnMut(&mut I, &MutCtx, IA) -> Result + 'static { + MutMethod(MutMethods::MutIface(Box::new(move |data, info| { + let iface: &mut I = data.downcast_mut().unwrap(); + let ia = match IA::read(info.msg()) { + Err(e) => return Some(MethodErr::from(e).to_message(info.msg())), + Ok(ia) => ia, + }; + match f(iface, info, ia) { + Err(e) => Some(e.to_message(info.msg())), + Ok(r) => { + let mut m = info.msg().method_return(); + OA::append(r, &mut m); + Some(m) + }, + } + }))) + } +} diff --git a/third_party/rust/dbus/src/crossroads/info.rs b/third_party/rust/dbus/src/crossroads/info.rs new file mode 100644 index 0000000000..655b3193de --- /dev/null +++ b/third_party/rust/dbus/src/crossroads/info.rs @@ -0,0 +1,220 @@ +use crate::{Path as PathName, Interface as IfaceName, Member as MemberName, Signature, Message}; +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::any::Any; +use std::mem; +use crate::arg::{Arg, Append, Get, ArgBuilder, TypeMismatchError, IterAppend}; +use std::marker::PhantomData; +use super::MethodErr; +use super::handlers::{Handlers, DebugMethod, DebugProp, Par, ParInfo, Mut, MutCtx}; +use super::crossroads::{Crossroads, PathData}; + +fn build_argvec(a: A::strs) -> Vec> { + let mut v = vec!(); + A::strs_sig(a, |name, sig| { + v.push(Argument { name: name.into(), sig }) + }); + v +} + + +#[derive(Default, Debug, Clone)] +struct Annotations(Option>); + +#[derive(Debug, Clone)] +pub struct Argument<'a> { + name: Cow<'a, str>, + sig: Signature<'a>, +} + +#[derive(Debug)] +pub struct IfaceInfo<'a, H: Handlers> { + pub (crate) name: IfaceName<'a>, + pub (crate) methods: Vec>, + pub (crate) props: Vec>, + pub (crate) signals: Vec>, +} + +#[derive(Debug)] +pub struct MethodInfo<'a, H: Handlers> { + name: MemberName<'a>, + handler: DebugMethod, + i_args: Vec>, + o_args: Vec>, + anns: Annotations, +} + +impl<'a, H: Handlers> MethodInfo<'a, H> { + pub fn name(&self) -> &MemberName<'a> { &self.name } + pub fn handler(&self) -> &H::Method { &self.handler.0 } + pub fn handler_mut(&mut self) -> &mut H::Method { &mut self.handler.0 } +} + +#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)] +/// Enumerates the different signaling behaviors a Property can have +/// to being changed. +pub enum EmitsChangedSignal { + /// The Property emits a signal that includes the new value. + True, + /// The Property emits a signal that does not include the new value. + Invalidates, + /// The Property cannot be changed. + Const, + /// The Property does not emit a signal when changed. + False, +} + +#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)] +/// The possible access characteristics a Property can have. +pub enum Access { + /// The Property can only be read (Get). + Read, + /// The Property can be read or written. + ReadWrite, + /// The Property can only be written (Set). + Write, +} + +#[derive(Debug)] +pub struct PropInfo<'a, H: Handlers> { + pub (crate) name: MemberName<'a>, + pub (crate) handlers: DebugProp, + anns: Annotations, + sig: Signature<'a>, + emits: EmitsChangedSignal, + auto_emit: bool, + rw: Access, +} + +#[derive(Debug)] +pub struct SignalInfo<'a> { + name: MemberName<'a>, + args: Vec>, + anns: Annotations, +} + +#[derive(Debug)] +pub struct IfaceInfoBuilder<'a, I: 'static, H: Handlers> { + cr: Option<&'a mut Crossroads>, + info: IfaceInfo<'static, H>, + _dummy: PhantomData<*const I>, +} + +impl<'a, I, H: Handlers> IfaceInfoBuilder<'a, I, H> { + pub fn new(cr: Option<&'a mut Crossroads>, name: IfaceName<'static>) -> Self { + IfaceInfoBuilder { cr, _dummy: PhantomData, info: IfaceInfo::new_empty(name) } + } + + pub fn signal>>(mut self, name: N, args: A::strs) -> Self { + let s = SignalInfo { name: name.into(), args: build_argvec::(args), anns: Default::default() }; + self.info.signals.push(s); + self + } +} + +impl<'a, I: 'static, H: Handlers> Drop for IfaceInfoBuilder<'a, I, H> { + fn drop(&mut self) { + if let Some(ref mut cr) = self.cr { + let info = IfaceInfo::new_empty(self.info.name.clone()); // workaround for not being able to consume self.info + cr.register_custom::(mem::replace(&mut self.info, info)); + } + } +} + +impl<'a, I: 'static> IfaceInfoBuilder<'a, I, Par> { + pub fn method(mut self, name: N, in_args: IA::strs, out_args: OA::strs, f: F) -> Self + where N: Into>, F: Fn(&I, &ParInfo, IA) -> Result + Send + Sync + 'static { + let f: ::Method = Box::new(move |data, info| { + let iface: &I = data.downcast_ref().unwrap(); + let r = IA::read(info.msg()).map_err(From::from); + let r = r.and_then(|ia| f(iface, info, ia)); + match r { + Err(e) => Some(e.to_message(info.msg())), + Ok(r) => { + let mut m = info.msg().method_return(); + OA::append(r, &mut m); + Some(m) + }, + } + }); + + let m = MethodInfo { name: name.into(), handler: DebugMethod(f), + i_args: build_argvec::(in_args), o_args: build_argvec::(out_args), anns: Default::default() }; + self.info.methods.push(m); + self + } + + pub fn prop_rw(mut self, name: N, getf: G, setf: S) -> Self + where T: Arg + Append + for<'z> Get<'z> + Send + Sync + 'static, + N: Into>, + G: Fn(&I, &ParInfo) -> Result + Send + Sync + 'static, + S: Fn(&I, &ParInfo, T) -> Result<(), MethodErr> + Send + Sync + 'static + { + let p = PropInfo::new(name.into(), T::signature(), Some(Par::typed_getprop(getf)), Some(Par::typed_setprop(setf))); + self.info.props.push(p); + self + } + + pub fn prop_ro(mut self, name: N, getf: G) -> Self + where T: Arg + Append + Send + Sync + 'static, + N: Into>, + G: Fn(&I, &ParInfo) -> Result + Send + Sync + 'static, + { + let p = PropInfo::new(name.into(), T::signature(), Some(Par::typed_getprop(getf)), None); + self.info.props.push(p); + self + } + +} + +impl<'a, I: 'static> IfaceInfoBuilder<'a, I, Mut> { + pub fn method_iface(mut self, name: N, in_args: IA::strs, out_args: OA::strs, f: F) -> Self + where N: Into>, F: FnMut(&mut I, &MutCtx, IA) -> Result + Send + Sync + 'static { + let m = MethodInfo { name: name.into(), handler: DebugMethod(Mut::typed_method_iface(f)), + i_args: build_argvec::(in_args), o_args: build_argvec::(out_args), anns: Default::default() }; + self.info.methods.push(m); + self + } +} + +impl MethodInfo<'_, H> { + pub fn new(name: MemberName<'static>, f: H::Method) -> Self { + MethodInfo { name: name, handler: DebugMethod(f), + i_args: Default::default(), o_args: Default::default(), anns: Default::default() } + } +} + +impl PropInfo<'_, H> { + pub fn new(name: MemberName<'static>, sig: Signature<'static>, get: Option, + set: Option) -> Self { + let a = match (&get, &set) { + (Some(_), Some(_)) => Access::ReadWrite, + (Some(_), None) => Access::Read, + (None, Some(_)) => Access::Write, + _ => unimplemented!(), + }; + PropInfo { name, handlers: DebugProp(get, set), sig, auto_emit: true, rw: a, + emits: EmitsChangedSignal::True, anns: Default::default() } + } +} + +impl<'a, H: Handlers> IfaceInfo<'a, H> { + pub fn new_empty(name: IfaceName<'static>) -> Self { + IfaceInfo { name, methods: vec!(), props: vec!(), signals: vec!() } + } + + pub fn new(name: N, methods: M, properties: P, signals: S) -> Self where + N: Into>, + M: IntoIterator>, + P: IntoIterator>, + S: IntoIterator> + { + IfaceInfo { + name: name.into(), + methods: methods.into_iter().collect(), + props: properties.into_iter().collect(), + signals: signals.into_iter().collect() + } + } +} + diff --git a/third_party/rust/dbus/src/crossroads/mod.rs b/third_party/rust/dbus/src/crossroads/mod.rs new file mode 100644 index 0000000000..7915157bc1 --- /dev/null +++ b/third_party/rust/dbus/src/crossroads/mod.rs @@ -0,0 +1,15 @@ +//! Will eventually superseed the "tree" module. It's unstable and experimental for now. +#![allow(unused_imports, dead_code, missing_docs)] + +mod info; +mod handlers; +mod crossroads; +mod stdimpl; + +pub use crate::tree::MethodErr as MethodErr; + +pub use self::info::{IfaceInfo, MethodInfo, PropInfo}; + +pub use self::crossroads::{Crossroads, PathData}; + +pub use self::handlers::{Handlers, Par, ParInfo}; diff --git a/third_party/rust/dbus/src/crossroads/stdimpl.rs b/third_party/rust/dbus/src/crossroads/stdimpl.rs new file mode 100644 index 0000000000..10729da5b1 --- /dev/null +++ b/third_party/rust/dbus/src/crossroads/stdimpl.rs @@ -0,0 +1,53 @@ +use super::crossroads::Crossroads; +use super::handlers::{ParInfo, Par}; +use super::info::{IfaceInfo, MethodInfo, PropInfo}; +use crate::arg; +use super::MethodErr; + +pub struct DBusProperties; + +impl DBusProperties { + pub fn register(cr: &mut Crossroads) { + cr.register_custom::(IfaceInfo::new("org.freedesktop.DBus.Properties", + vec!(MethodInfo::new_par("Get", |_: &DBusProperties, info| { + let (iname, propname) = info.msg().read2()?; + let (lookup, pinfo) = info.crossroads().reg_prop_lookup(info.path_data(), iname, propname) + .ok_or_else(|| { MethodErr::no_property(&"Could not find property") })?; + let handler = &pinfo.handlers.0.as_ref() + .ok_or_else(|| { MethodErr::no_property(&"Property can not be read") })?; + let iface = &**lookup.iface; + let mut pinfo = ParInfo::new(info.msg(), lookup); + let mut mret = info.msg().method_return(); + { + let mut ia = arg::IterAppend::new(&mut mret); + (handler)(iface, &mut ia, &mut pinfo)?; + } + Ok(Some(mret)) + })), + vec!(), vec!() + )); + + } +} + +pub struct DBusIntrospectable; + +use crate::crossroads as cr; + +pub trait Introspectable { + fn introspect(&self, info: &cr::ParInfo) -> Result; +} + +pub fn introspectable_ifaceinfo() -> cr::IfaceInfo<'static, cr::Par> +where I: Introspectable + Send + Sync + 'static { + cr::IfaceInfo::new("org.freedesktop.DBus.Introspectable", vec!( + MethodInfo::new_par("Introspect", |intf: &I, info| { + let xml_data = intf.introspect(info)?; + let rm = info.msg().method_return(); + let rm = rm.append1(xml_data); + Ok(Some(rm)) + }), + ), vec!(), vec!()) +} + + -- cgit v1.2.3