dbus_message_parser/match_rule/
matching.rs

1use super::MatchRule;
2use crate::{
3    message::Message,
4    value::{Bus, Value},
5};
6
7fn match_namespace<const P: char>(namespace: &str, value: &str) -> bool {
8    if let Some(value) = value.strip_prefix(namespace) {
9        value.starts_with(P) || value.is_empty()
10    } else {
11        false
12    }
13}
14
15fn get_str_from_string_or_object_path(value: &Value) -> Option<&str> {
16    match value {
17        Value::String(string) => Some(string),
18        Value::ObjectPath(object_path) => Some(object_path.as_ref()),
19        _ => None,
20    }
21}
22
23impl MatchRule {
24    pub fn matching_rule(&self, message: &Message) -> bool {
25        match self {
26            MatchRule::Type(r#type) => r#type == &message.get_type(),
27            MatchRule::Sender(sender_1) => {
28                if let Some(sender_2) = message.get_sender() {
29                    sender_1 == sender_2
30                } else {
31                    false
32                }
33            }
34            MatchRule::Interface(interface_1) => {
35                if let Some(interface_2) = message.get_interface() {
36                    interface_1 == interface_2
37                } else {
38                    false
39                }
40            }
41            MatchRule::Member(member_1) => {
42                if let Some(member_2) = message.get_member() {
43                    member_1 == member_2
44                } else {
45                    false
46                }
47            }
48            MatchRule::Path(path_1) => {
49                if let Some(path_2) = message.get_path() {
50                    path_1 == path_2
51                } else {
52                    false
53                }
54            }
55            MatchRule::PathNamespace(path_namespace) => {
56                if let Some(path) = message.get_path() {
57                    match_namespace::<'/'>(path_namespace.as_ref(), path.as_ref())
58                } else {
59                    false
60                }
61            }
62            MatchRule::Destination(destination_1) => {
63                if let Some(destination_2) = message.get_destination() {
64                    match destination_2 {
65                        Bus::WellKnownBusName(_) => false,
66                        Bus::UniqueConnectionName(destination_2) => destination_1 == destination_2,
67                    }
68                } else {
69                    false
70                }
71            }
72            MatchRule::Arg(arg) => {
73                let body = message.get_body();
74                if let Some(Value::String(value)) = body.get(arg.get_index()) {
75                    arg.get_value() == value
76                } else {
77                    false
78                }
79            }
80            MatchRule::ArgPath(arg_path) => {
81                let body = message.get_body();
82                if let Some(value) = body.get(arg_path.get_index()) {
83                    if let Some(string) = get_str_from_string_or_object_path(value) {
84                        match_namespace::<'/'>(arg_path.get_value().as_ref(), string)
85                    } else {
86                        false
87                    }
88                } else {
89                    false
90                }
91            }
92            MatchRule::Arg0Namespace(arg0_namespace) => {
93                let body = message.get_body();
94                if let Some(Value::String(arg0)) = body.get(0) {
95                    match_namespace::<'.'>(arg0_namespace.as_ref(), arg0)
96                } else {
97                    false
98                }
99            }
100            MatchRule::Eavesdrop(_) => true,
101        }
102    }
103
104    pub fn matching_rules(match_rules: &[MatchRule], message: &Message) -> bool {
105        for match_rule in match_rules.iter() {
106            if !match_rule.matching_rule(message) {
107                return false;
108            }
109        }
110        true
111    }
112}