in rust/azure_iot_operations_mqtt/src/topic.rs [220:285]
fn check_topic_filter(topic_filter: &str) -> Result<(), TopicParseError> {
let mut prev_ml_wildcard = false;
let mut levels = topic_filter.split(LEVEL_SEPARATOR);
let mut filter_levels_length = 0;
// Used to check if the first level of the topic filter is empty to account for the case
// where a shared subscription topic filter is used with an empty topic filter, i.e "$share/consumer1/"
let mut first_topic_filter_level_empty = false;
if is_shared_sub(topic_filter) {
// Skip $share
levels.next();
// The ShareName MUST NOT contain the characters "/", "+" or "#", but MUST be followed by a "/" character. This "/" character MUST be followed by a Topic Filter (4.8.2)
match levels.next() {
Some(share_name) => {
if share_name.contains(MULTI_LEVEL_WILDCARD)
|| share_name.contains(SINGLE_LEVEL_WILDCARD)
|| share_name.is_empty()
{
return Err(TopicParseError::InvalidShareName(topic_filter.to_string()));
}
}
None => {
// No share name
return Err(TopicParseError::SharedSubscriptionTooShort(
topic_filter.to_string(),
));
}
}
}
// NOTE: Adjacent topic filter level separators ("/") are valid and indicate a zero length topic level (4.7.1.1)
// NOTE: Topic filters can contain the space (" ") character (4.7.3)
for level in levels {
filter_levels_length += 1;
// Check if the first level of the topic filter is empty
if filter_levels_length == 1 && level.is_empty() {
first_topic_filter_level_empty = true;
}
if prev_ml_wildcard {
// Multi-level wildcard MUST be the last character specified (4.7.1.2)
return Err(TopicParseError::WildcardNotLast(topic_filter.to_string()));
}
if level.contains(MULTI_LEVEL_WILDCARD) {
// Multi-level wildcard MUST occupy an entire level of the topic filter (4.7.1.2)
if level != MULTI_LEVEL_WILDCARD {
return Err(TopicParseError::WildcardNotAlone(topic_filter.to_string()));
}
prev_ml_wildcard = true;
}
if level.contains(SINGLE_LEVEL_WILDCARD) {
// Single-level wildcard MUST occupy an entire level of the topic filter (4.7.1.3)
if level != SINGLE_LEVEL_WILDCARD {
return Err(TopicParseError::WildcardNotAlone(topic_filter.to_string()));
}
}
}
// Topic filters must be at least one character long (4.7.3)
if filter_levels_length == 0
|| (first_topic_filter_level_empty && filter_levels_length == 1)
{
return Err(TopicParseError::Empty);
}
Ok(())
}