public static PatternValidity ValidateTopicPattern()

in dotnet/src/Azure.Iot.Operations.Protocol/MqttTopicProcessor.cs [77:165]


        public static PatternValidity ValidateTopicPattern(
            string? pattern,
            IReadOnlyDictionary<string, string>? tokenMap,
            bool requireReplacement,
            out string errMsg,
            out string? errToken,
            out string? errReplacement)
        {
            errToken = null;
            errReplacement = null;

            if (string.IsNullOrEmpty(pattern))
            {
                errMsg = "MQTT topic pattern must not be empty";
                return PatternValidity.InvalidPattern;
            }

            if (pattern.StartsWith('$'))
            {
                errMsg = "MQTT topic pattern starts with reserved character '$'";
                return PatternValidity.InvalidPattern;
            }

            foreach (string level in pattern.Split('/'))
            {
                if (level.Length == 0)
                {
                    errMsg = "MQTT topic pattern contains empty level";
                    return PatternValidity.InvalidPattern;
                }

                bool isToken = level.StartsWith('{') && level.EndsWith('}');
                if (isToken)
                {
                    string token = level[1..^1];
                    if (token.Length == 0)
                    {
                        errMsg = "Token in MQTT topic pattern is empty";
                        return PatternValidity.InvalidPattern;
                    }
                    else if (ContainsInvalidChar(token))
                    {
                        errMsg = $"Token '{level}' in MQTT topic pattern contains invalid character";
                        return PatternValidity.InvalidPattern;
                    }
                    else if (tokenMap == null)
                    {
                        if (requireReplacement)
                        {
                            errMsg = $"Token '{level}' in MQTT topic pattern, but no replacement map value provided";
                            errToken = token;
                            return PatternValidity.MissingReplacement;
                        }
                    }
                    else
                    {
                        string? replacement = null;
                        bool hasReplacement = tokenMap != null && tokenMap.TryGetValue(token, out replacement);
                        if (!hasReplacement)
                        {
                            if (requireReplacement)
                            {
                                errMsg = $"Token '{level}' in MQTT topic pattern, but key '{token}' not found in replacement map";
                                errToken = token;
                                return PatternValidity.MissingReplacement;
                            }
                        }
                        else if (hasReplacement && !IsValidReplacement(replacement))
                        {
                            errMsg = $"Token '{level}' in MQTT topic pattern has resident replacement value '{replacement}' that is not valid";
                            errToken = token;
                            errReplacement = replacement;
                            return PatternValidity.InvalidResidentReplacement;
                        }
                    }
                }
                else
                {
                    if (ContainsInvalidChar(level))
                    {
                        errMsg = $"Level '{level}' in MQTT topic pattern contains invalid character";
                        return PatternValidity.InvalidPattern;
                    }
                }
            }

            errMsg = string.Empty;
            return PatternValidity.Valid;
        }