aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs115
1 files changed, 2 insertions, 113 deletions
diff --git a/src/main.rs b/src/main.rs
index b071620..c2a3797 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -14,6 +14,7 @@ use rumqttc::{Event::Incoming, Packet, Publish, QoS};
use tokio::{io::AsyncWriteExt, process::Command, time::timeout};
mod config;
+mod mqtt;
const PROGRAM: &str = "mqttr";
@@ -41,40 +42,6 @@ async fn run(program: &[String], message: &Publish) -> anyhow::Result<ExitStatus
Ok(result)
}
-fn topic_match(filter: &str, topic: &str) -> bool {
- // TODO: Should probably just be a panic or prevented using types
- if filter.is_empty() || topic.is_empty() {
- return false;
- }
- if topic.starts_with('$') && (filter.starts_with('+') || filter.starts_with('#')) {
- return false;
- }
-
- // zip_longest would be nice
- let mut topic = topic.split('/');
- let mut filter = filter.split('/');
- loop {
- let topic_level = topic.next();
- return match filter.next() {
- Some("#") => filter.next().is_none(),
- Some("+") => {
- if topic_level.is_none() {
- false
- } else {
- continue;
- }
- }
- Some(filter_level) => match topic_level {
- Some(topic_level) if topic_level == filter_level => {
- continue;
- }
- _ => false,
- },
- None => topic_level.is_none(),
- };
- }
-}
-
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let mut conf_path: PathBuf = option_env!("SYSCONFDIR").unwrap_or("/usr/local/etc").into();
@@ -109,7 +76,7 @@ async fn main() -> anyhow::Result<()> {
debug!("Received message: {p:?}");
let p = Rc::new(p);
for (topic, route) in conf.routes.iter() {
- if !topic_match(topic, &p.topic) {
+ if !mqtt::topic_match(topic, &p.topic) {
continue;
}
debug!("Message {p:?} matched topic {topic}");
@@ -149,81 +116,3 @@ async fn main() -> anyhow::Result<()> {
})
.await
}
-
-#[cfg(test)]
-mod tests {
- use super::topic_match;
-
- #[test]
- fn topic_match_basic() {
- assert!(topic_match("foo/bar/baz", "foo/bar/baz"));
- assert!(!topic_match("foo/bar/baz", "foo/bar/qux"));
- assert!(!topic_match("foo/bar", "foo/bar/baz"));
- assert!(!topic_match("foo/bar/baz", "foo/bar"));
- }
-
- #[test]
- fn topic_match_wildcard_hash() {
- assert!(topic_match("foo/bar/baz/#", "foo/bar/baz"));
- assert!(topic_match("foo/bar/baz/#", "foo/bar/baz/qux"));
- assert!(topic_match("foo/bar/baz/#", "foo/bar/baz/qux/quux"));
- assert!(topic_match("#", "foo/bar/baz"));
- assert!(topic_match("#", "foo"));
- assert!(topic_match("#", "/"));
- assert!(topic_match("#", "/foo"));
- assert!(!topic_match("foo/bar/#", "foo/baz/bar"));
- assert!(!topic_match("foo/bar/#", "foo"));
- }
-
- #[test]
- fn topic_match_wildcard_plus() {
- assert!(topic_match("foo/bar/+", "foo/bar/baz"));
- assert!(topic_match("foo/bar/+", "foo/bar/qux"));
- assert!(!topic_match("foo/bar/+", "foo/bar/baz/qux"));
- assert!(topic_match("foo/+", "foo/"));
- assert!(!topic_match("foo/+", "foo"));
- assert!(topic_match("+", "foo"));
- assert!(topic_match("+/bar/#", "foo/bar/baz/qux"));
- assert!(topic_match("+/bar/#", "qux/bar"));
- assert!(topic_match("foo/+/baz", "foo/bar/baz"));
- assert!(topic_match("foo/+/baz", "foo/qux/baz"));
- assert!(!topic_match("foo/+/baz", "foo/bar/qux"));
- assert!(topic_match("+/+", "/foo"));
- assert!(topic_match("/+", "/foo"));
- assert!(!topic_match("+", "/foo"));
- }
-
- #[test]
- fn topic_match_dollar() {
- assert!(!topic_match("#", "$foo/bar"));
- assert!(!topic_match("+/bar/baz", "$foo/bar/baz"));
- assert!(topic_match("$foo/#", "$foo/bar"));
- assert!(topic_match("$foo/#", "$foo/bar/baz"));
- assert!(topic_match("$foo/#", "$foo"));
- assert!(topic_match("$foo/bar/+", "$foo/bar/baz"));
- assert!(!topic_match("$foo/#", "foo/bar"));
- }
-
- #[test]
- fn topic_match_edge_cases() {
- assert!(!topic_match("foo", "FOO"));
- assert!(topic_match("foo bar", "foo bar"));
- assert!(!topic_match("foo bar", "foo bar"));
- assert!(!topic_match("foo bar", "foo bar"));
- assert!(!topic_match("/foo", "foo"));
- assert!(!topic_match("foo", "/foo"));
- assert!(topic_match("foo//bar", "foo//bar"));
- assert!(!topic_match("foo/bar", "foo//bar"));
- assert!(!topic_match("foo//bar", "foo/bar"));
- assert!(!topic_match("foo//baz", "foo/bar/baz"));
- assert!(!topic_match("foo/bar/baz", "foo//baz"));
- assert!(topic_match("foo/+/baz", "foo//baz"));
- assert!(topic_match("/", "/"));
- assert!(!topic_match("/", "foo"));
- assert!(!topic_match("foo", "/"));
- assert!(!topic_match("", ""));
- assert!(!topic_match("+", ""));
- assert!(!topic_match("#", ""));
- assert!(!topic_match("foo/#/baz", "foo/bar/baz"));
- }
-}