summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dbus/src/crossroads/info.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/dbus/src/crossroads/info.rs')
-rw-r--r--third_party/rust/dbus/src/crossroads/info.rs220
1 files changed, 220 insertions, 0 deletions
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: ArgBuilder>(a: A::strs) -> Vec<Argument<'static>> {
+ 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<BTreeMap<String, String>>);
+
+#[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<MethodInfo<'a, H>>,
+ pub (crate) props: Vec<PropInfo<'a, H>>,
+ pub (crate) signals: Vec<SignalInfo<'a>>,
+}
+
+#[derive(Debug)]
+pub struct MethodInfo<'a, H: Handlers> {
+ name: MemberName<'a>,
+ handler: DebugMethod<H>,
+ i_args: Vec<Argument<'a>>,
+ o_args: Vec<Argument<'a>>,
+ 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<H>,
+ anns: Annotations,
+ sig: Signature<'a>,
+ emits: EmitsChangedSignal,
+ auto_emit: bool,
+ rw: Access,
+}
+
+#[derive(Debug)]
+pub struct SignalInfo<'a> {
+ name: MemberName<'a>,
+ args: Vec<Argument<'a>>,
+ anns: Annotations,
+}
+
+#[derive(Debug)]
+pub struct IfaceInfoBuilder<'a, I: 'static, H: Handlers> {
+ cr: Option<&'a mut Crossroads<H>>,
+ 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<H>>, name: IfaceName<'static>) -> Self {
+ IfaceInfoBuilder { cr, _dummy: PhantomData, info: IfaceInfo::new_empty(name) }
+ }
+
+ pub fn signal<A: ArgBuilder, N: Into<MemberName<'static>>>(mut self, name: N, args: A::strs) -> Self {
+ let s = SignalInfo { name: name.into(), args: build_argvec::<A>(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::<I>(mem::replace(&mut self.info, info));
+ }
+ }
+}
+
+impl<'a, I: 'static> IfaceInfoBuilder<'a, I, Par> {
+ pub fn method<IA: ArgBuilder, OA: ArgBuilder, N, F>(mut self, name: N, in_args: IA::strs, out_args: OA::strs, f: F) -> Self
+ where N: Into<MemberName<'static>>, F: Fn(&I, &ParInfo, IA) -> Result<OA, MethodErr> + Send + Sync + 'static {
+ let f: <Par as Handlers>::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::<IA>(in_args), o_args: build_argvec::<OA>(out_args), anns: Default::default() };
+ self.info.methods.push(m);
+ self
+ }
+
+ pub fn prop_rw<T, N, G, S>(mut self, name: N, getf: G, setf: S) -> Self
+ where T: Arg + Append + for<'z> Get<'z> + Send + Sync + 'static,
+ N: Into<MemberName<'static>>,
+ G: Fn(&I, &ParInfo) -> Result<T, MethodErr> + 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<T, N, G>(mut self, name: N, getf: G) -> Self
+ where T: Arg + Append + Send + Sync + 'static,
+ N: Into<MemberName<'static>>,
+ G: Fn(&I, &ParInfo) -> Result<T, MethodErr> + 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<IA: ArgBuilder, OA: ArgBuilder, N, F>(mut self, name: N, in_args: IA::strs, out_args: OA::strs, f: F) -> Self
+ where N: Into<MemberName<'static>>, F: FnMut(&mut I, &MutCtx, IA) -> Result<OA, MethodErr> + Send + Sync + 'static {
+ let m = MethodInfo { name: name.into(), handler: DebugMethod(Mut::typed_method_iface(f)),
+ i_args: build_argvec::<IA>(in_args), o_args: build_argvec::<OA>(out_args), anns: Default::default() };
+ self.info.methods.push(m);
+ self
+ }
+}
+
+impl<H: Handlers> 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<H: Handlers> PropInfo<'_, H> {
+ pub fn new(name: MemberName<'static>, sig: Signature<'static>, get: Option<H::GetProp>,
+ set: Option<H::SetProp>) -> 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<N, M, P, S>(name: N, methods: M, properties: P, signals: S) -> Self where
+ N: Into<IfaceName<'a>>,
+ M: IntoIterator<Item=MethodInfo<'a, H>>,
+ P: IntoIterator<Item=PropInfo<'a, H>>,
+ S: IntoIterator<Item=SignalInfo<'a>>
+ {
+ IfaceInfo {
+ name: name.into(),
+ methods: methods.into_iter().collect(),
+ props: properties.into_iter().collect(),
+ signals: signals.into_iter().collect()
+ }
+ }
+}
+