summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dbus/src/matchrule.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/dbus/src/matchrule.rs')
-rw-r--r--third_party/rust/dbus/src/matchrule.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/third_party/rust/dbus/src/matchrule.rs b/third_party/rust/dbus/src/matchrule.rs
new file mode 100644
index 0000000000..fb42abe51b
--- /dev/null
+++ b/third_party/rust/dbus/src/matchrule.rs
@@ -0,0 +1,77 @@
+use crate::{Message, MessageType, BusName, Path, Interface, Member};
+
+
+#[derive(Clone, Debug, Default)]
+/// A "match rule", that can match Messages on its headers.
+///
+/// A field set to "None" means no filter for that header,
+/// a field set to "Some(_)" must match exactly.
+pub struct MatchRule<'a> {
+ /// Match on message type (you typically want to do this)
+ pub msg_type: Option<MessageType>,
+ /// Match on message sender
+ pub sender: Option<BusName<'a>>,
+ /// Match on message object path
+ pub path: Option<Path<'a>>,
+ /// Match on message interface
+ pub interface: Option<Interface<'a>>,
+ /// Match on message member (signal or method name)
+ pub member: Option<Member<'a>>,
+ _more_fields_may_come: (),
+}
+
+fn msg_type_str(m: MessageType) -> &'static str {
+ use MessageType::*;
+ match m {
+ Signal => "signal",
+ MethodCall => "method_call",
+ MethodReturn => "method_return",
+ Error => "error",
+ Invalid => unreachable!(),
+ }
+}
+
+
+impl<'a> MatchRule<'a> {
+ /// Make a string which you can use in the call to "add_match".
+ ///
+ /// Panics: if msg_type is set to Some(MessageType::Invalid)
+ pub fn match_str(&self) -> String {
+ let mut v = vec!();
+ if let Some(x) = self.msg_type { v.push(("type", msg_type_str(x))) };
+ if let Some(ref x) = self.sender { v.push(("sender", &x)) };
+ if let Some(ref x) = self.path { v.push(("path", &x)) };
+ if let Some(ref x) = self.interface { v.push(("interface", &x)) };
+ if let Some(ref x) = self.member { v.push(("member", &x)) };
+
+ // For now we don't need to worry about internal quotes in strings as those are not valid names.
+ // If we start matching against arguments, we need to worry.
+ let v: Vec<_> = v.into_iter().map(|(k, v)| format!("{}='{}'", k, v)).collect();
+ v.join(",")
+ }
+
+ /// Returns whether or not the message matches the rule.
+ pub fn matches(&self, msg: &Message) -> bool {
+ if let Some(x) = self.msg_type { if x != msg.msg_type() { return false; }};
+ if self.sender.is_some() && msg.sender() != self.sender { return false };
+ if self.path.is_some() && msg.path() != self.path { return false };
+ if self.interface.is_some() && msg.interface() != self.interface { return false };
+ if self.member.is_some() && msg.member() != self.member { return false };
+ true
+ }
+
+ /// Create a new struct which matches every message.
+ pub fn new() -> Self { Default::default() }
+
+ /// Returns a clone with no static references
+ pub fn into_static(&self) -> MatchRule<'static> {
+ MatchRule {
+ msg_type: self.msg_type,
+ sender: self.sender.as_ref().map(|x| x.clone().into_static()),
+ path: self.path.as_ref().map(|x| x.clone().into_static()),
+ interface: self.interface.as_ref().map(|x| x.clone().into_static()),
+ member: self.member.as_ref().map(|x| x.clone().into_static()),
+ _more_fields_may_come: (),
+ }
+ }
+}