1use crate::Pattern;
2
3use std::mem;
4
5macro_rules! unwrap_msg {
6 ($variant:tt, $func_name:ident) => {
7 pub fn $func_name(self) -> Pattern {
8 match self {
9 Message::$variant(pattern) => pattern,
10 _ => panic!("Expected Message variant $variant, got {:?}", self),
11 }
12 }
13 };
14}
15
16#[derive(Clone, Debug, Eq, Hash, PartialEq)]
17pub enum Message {
18 Provide(Pattern),
19 Revoke(Pattern),
20 Subscribe(Pattern),
21 Unsubscribe(Pattern),
22 Event(Pattern, String),
23}
24
25impl Message {
26 #[allow(clippy::trivially_copy_pass_by_ref)]
31 pub fn test_poor_mans_discriminant(discriminant: &u8) -> bool {
32 *discriminant <= 4
33 }
34
35 pub fn from_poor_mans_discriminant(
39 discriminant: u8,
40 namespace: Pattern,
41 data: Option<String>,
42 ) -> Self {
43 match discriminant {
44 0 => Message::Provide(namespace),
45 1 => Message::Revoke(namespace),
46 2 => Message::Subscribe(namespace),
47 3 => Message::Unsubscribe(namespace),
48 4 => Message::Event(
49 namespace,
50 data.expect("Data must be present for Message::Event type"),
51 ),
52 _ => panic!("Invalid discriminant {}", discriminant),
53 }
54 }
55
56 unwrap_msg!(Provide, unwrap_provide);
59 unwrap_msg!(Revoke, unwrap_revoke);
60 unwrap_msg!(Subscribe, unwrap_subscribe);
61 unwrap_msg!(Unsubscribe, unwrap_unsubscribe);
62
63 pub fn namespace(&self) -> &Pattern {
65 match self {
66 Message::Provide(p) => p,
67 Message::Revoke(p) => p,
68 Message::Subscribe(p) => p,
69 Message::Unsubscribe(p) => p,
70 Message::Event(p, _) => p,
71 }
72 }
73
74 pub fn poor_mans_discriminant(&self) -> u8 {
81 match self {
82 Message::Provide(_) => 0,
83 Message::Revoke(_) => 1,
84 Message::Subscribe(_) => 2,
85 Message::Unsubscribe(_) => 3,
86 Message::Event(_, _) => 4,
87 }
88 }
89
90 pub fn contains(&self, other: &Message) -> bool {
91 mem::discriminant(self) == mem::discriminant(other)
92 && self.namespace().contains(other.namespace())
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_poor_mans_discriminant() {
102 let pattern = Pattern::new("/");
103
104 let provide = Message::Provide(pattern.clone());
105 assert_eq!(
106 Message::from_poor_mans_discriminant(
107 provide.poor_mans_discriminant(),
108 pattern.clone(),
109 None
110 ),
111 provide
112 );
113
114 let revoke = Message::Revoke(pattern.clone());
115 assert_eq!(
116 Message::from_poor_mans_discriminant(
117 revoke.poor_mans_discriminant(),
118 pattern.clone(),
119 None
120 ),
121 revoke
122 );
123
124 let subscribe = Message::Subscribe(pattern.clone());
125 assert_eq!(
126 Message::from_poor_mans_discriminant(
127 subscribe.poor_mans_discriminant(),
128 pattern.clone(),
129 None
130 ),
131 subscribe
132 );
133
134 let unsubscribe = Message::Unsubscribe(pattern.clone());
135 assert_eq!(
136 Message::from_poor_mans_discriminant(
137 unsubscribe.poor_mans_discriminant(),
138 pattern.clone(),
139 None
140 ),
141 unsubscribe
142 );
143
144 let event = Message::Event(pattern.clone(), String::new());
145 assert_eq!(
146 Message::from_poor_mans_discriminant(
147 event.poor_mans_discriminant(),
148 pattern,
149 Some(String::new())
150 ),
151 event
152 );
153 }
154
155 #[test]
156 fn test_message_contains() {
157 let message = Message::Provide("/a".into());
158
159 assert!(message.contains(&Message::Provide("/a".into())));
161 assert!(message.contains(&Message::Provide("/a/b".into())));
163 assert!(!message.contains(&Message::Revoke("/a".into())));
165 assert!(!message.contains(&Message::Provide("/c".into())));
167
168 assert!(Message::Event("/a".into(), String::new())
170 .contains(&Message::Event("/a".into(), "b".into())));
171
172 assert!(Message::Provide("/".into()).contains(&Message::Provide("/a/b/c".into())));
174 }
175}