use crate::mqtt::result_code::MqttError;
const SHARE_PREFIX: &str = "$share/";
pub fn validate_share_name(topic_filter: &str) -> Result<(), MqttError> {
if !topic_filter.starts_with(SHARE_PREFIX) {
return Ok(());
}
let after_prefix = &topic_filter[SHARE_PREFIX.len()..];
let separator_pos = after_prefix.find('/');
match separator_pos {
None => {
Err(MqttError::MalformedPacket)
}
Some(0) => {
Err(MqttError::MalformedPacket)
}
Some(pos) => {
let share_name = &after_prefix[..pos];
if share_name.contains('+') || share_name.contains('#') {
return Err(MqttError::MalformedPacket);
}
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_share_name_non_shared() {
assert!(validate_share_name("sensors/temperature").is_ok());
assert!(validate_share_name("home/+/status").is_ok());
assert!(validate_share_name("alerts/#").is_ok());
assert!(validate_share_name("$SYS/broker/uptime").is_ok());
assert!(validate_share_name("").is_ok());
}
#[test]
fn test_validate_share_name_valid_shared() {
assert!(validate_share_name("$share/mygroup/sensors/temperature").is_ok());
assert!(validate_share_name("$share/group1/home/+/status").is_ok());
assert!(validate_share_name("$share/consumers/alerts/#").is_ok());
assert!(validate_share_name("$share/a/topic").is_ok());
assert!(validate_share_name("$share/group-name/topic").is_ok());
assert!(validate_share_name("$share/group_name/topic").is_ok());
assert!(validate_share_name("$share/group.name/topic").is_ok());
}
#[test]
fn test_validate_share_name_invalid_contains_slash() {
assert!(validate_share_name("$share/my/group/topic").is_ok());
}
#[test]
fn test_validate_share_name_invalid_contains_plus() {
assert!(validate_share_name("$share/my+group/topic").is_err());
assert!(validate_share_name("$share/+/topic").is_err());
assert!(validate_share_name("$share/group+/topic").is_err());
}
#[test]
fn test_validate_share_name_invalid_contains_hash() {
assert!(validate_share_name("$share/my#group/topic").is_err());
assert!(validate_share_name("$share/#/topic").is_err());
assert!(validate_share_name("$share/group#/topic").is_err());
}
#[test]
fn test_validate_share_name_invalid_empty_share_name() {
assert!(validate_share_name("$share//topic").is_err());
}
#[test]
fn test_validate_share_name_invalid_no_filter() {
assert!(validate_share_name("$share/mygroup").is_err());
assert!(validate_share_name("$share/").is_err());
}
}