1 use crate::{Message, MessageType, BusName, Path, Interface, Member};
2 
3 
4 #[derive(Clone, Debug, Default)]
5 /// A "match rule", that can match Messages on its headers.
6 ///
7 /// A field set to "None" means no filter for that header,
8 /// a field set to "Some(_)" must match exactly.
9 pub struct MatchRule<'a> {
10     /// Match on message type (you typically want to do this)
11     pub msg_type: Option<MessageType>,
12     /// Match on message sender
13     pub sender: Option<BusName<'a>>,
14     /// Match on message object path
15     pub path: Option<Path<'a>>,
16     /// Match on message interface
17     pub interface: Option<Interface<'a>>,
18     /// Match on message member (signal or method name)
19     pub member: Option<Member<'a>>,
20     _more_fields_may_come: (),
21 }
22 
msg_type_str(m: MessageType) -> &'static str23 fn msg_type_str(m: MessageType) -> &'static str {
24     use MessageType::*;
25     match m {
26         Signal => "signal",
27         MethodCall => "method_call",
28         MethodReturn => "method_return",
29         Error => "error",
30         Invalid => unreachable!(),
31     }
32 }
33 
34 
35 impl<'a> MatchRule<'a> {
36     /// Make a string which you can use in the call to "add_match".
37     ///
38     /// Panics: if msg_type is set to Some(MessageType::Invalid)
match_str(&self) -> String39     pub fn match_str(&self) -> String {
40         let mut v = vec!();
41         if let Some(x) = self.msg_type { v.push(("type", msg_type_str(x))) };
42         if let Some(ref x) = self.sender { v.push(("sender", &x)) };
43         if let Some(ref x) = self.path { v.push(("path", &x)) };
44         if let Some(ref x) = self.interface { v.push(("interface", &x)) };
45         if let Some(ref x) = self.member { v.push(("member", &x)) };
46 
47         // For now we don't need to worry about internal quotes in strings as those are not valid names.
48         // If we start matching against arguments, we need to worry.
49         let v: Vec<_> = v.into_iter().map(|(k, v)| format!("{}='{}'", k, v)).collect();
50         v.join(",")
51     }
52 
53     /// Returns whether or not the message matches the rule.
matches(&self, msg: &Message) -> bool54     pub fn matches(&self, msg: &Message) -> bool {
55         if let Some(x) = self.msg_type { if x != msg.msg_type() { return false; }};
56         if self.sender.is_some() && msg.sender() != self.sender { return false };
57         if self.path.is_some() && msg.path() != self.path { return false };
58         if self.interface.is_some() && msg.interface() != self.interface { return false };
59         if self.member.is_some() && msg.member() != self.member { return false };
60         true
61     }
62 
63     /// Create a new struct which matches every message.
new() -> Self64     pub fn new() -> Self { Default::default() }
65 
66     /// Returns a clone with no static references
into_static(&self) -> MatchRule<'static>67     pub fn into_static(&self) -> MatchRule<'static> {
68         MatchRule {
69             msg_type: self.msg_type,
70             sender: self.sender.as_ref().map(|x| x.clone().into_static()),
71             path: self.path.as_ref().map(|x| x.clone().into_static()),
72             interface: self.interface.as_ref().map(|x| x.clone().into_static()),
73             member: self.member.as_ref().map(|x| x.clone().into_static()),
74             _more_fields_may_come: (),
75         }
76     }
77 }
78