package bus import ( "fmt" "strings" ) // match reports whether subject matches pattern using the wildcard rules // described in the package comment: "*" matches exactly one non-empty token, // ">" matches one or more trailing tokens and must be the last token, and any // other token matches an identical subject token. Callers must have validated // both inputs, so an empty token or a misplaced ">" never reaches here. func match(pattern, subject string) bool { p := strings.Split(pattern, ".") s := strings.Split(subject, ".") i, j := 0, 0 for i < len(p) { if p[i] == ">" { // ">" is guaranteed to be the last token; it needs at least one // remaining subject token. return j < len(s) } if j >= len(s) { return false } if p[i] != "*" && p[i] != s[j] { return false } i++ j++ } return j == len(s) } // validateSubject rejects an empty subject or one containing an empty token // (leading/trailing/repeated dots). func validateSubject(subject string) error { if subject == "" { return fmt.Errorf("bus: subject must not be empty: %w", ErrInvalidArgument) } if strings.HasPrefix(subject, ".") || strings.HasSuffix(subject, ".") || strings.Contains(subject, "..") { return fmt.Errorf("bus: subject %q contains an empty token: %w", subject, ErrInvalidArgument) } return nil } // validatePattern rejects an empty pattern, one with an empty token, or one // where the ">" wildcard is not the final token. func validatePattern(pattern string) error { if pattern == "" { return fmt.Errorf("bus: pattern must not be empty: %w", ErrInvalidArgument) } if strings.HasPrefix(pattern, ".") || strings.HasSuffix(pattern, ".") || strings.Contains(pattern, "..") { return fmt.Errorf("bus: pattern %q contains an empty token: %w", pattern, ErrInvalidArgument) } tokens := strings.Split(pattern, ".") for i, tok := range tokens { if tok == ">" && i != len(tokens)-1 { return fmt.Errorf("bus: pattern %q: '>' wildcard must be the last token: %w", pattern, ErrInvalidArgument) } } return nil }