Skip to main content

pattern_contains

Function pattern_contains 

Source
pub fn pattern_contains(grant: &str, requested: &str) -> bool
Expand description

Returns true if every topic matched by requested is also matched by grant — i.e. grant’s match set ⊇ requested’s match set (grant contains requested).

This is pattern containment, not topic matching, and the two diverge once requested is itself a wildcard. An access check must ask containment: “does my grant cover the whole pattern this client asked to subscribe to?” topic_matches answers a different question (“does this pattern match this string?”) and would treat the requested pattern as an opaque topic — so a one-level grant a.* “matches” the all-levels request a.# (the * swallows the #) and silently widens the grant. Containment denies that: a.# reaches deeper than a.* covers.

When requested is a concrete topic (no wildcard) this collapses to exactly topic_matches(grant, requested), so it is a safe drop-in for an ACL that must accept both concrete and wildcard subscription requests.

Grammar is the same dot-separated * (single-level) / # (multi-level, zero-or-more) set as topic_matches. A grant’s # absorbs zero or more requested segments and the grant continues after it, so an interior # constrains rather than blanket-allows: a.#.secret contains a.b.secret but not a.public.

§Conservative by construction

This decides containment with a single left-to-right walk, which is sound (it never reports containment that does not hold) but not complete. Deciding the remaining cases means reasoning about every expansion of the request’s #, and that ∀-branch is exactly the intricate, blowup-prone code an ACL on client-supplied input should not carry.

The gap is confined to a grant whose * meets a request’s #, where a later segment would have ruled out the short expansions — e.g. a.*.# does contain a.#.a (every topic the request admits has ≥2 segments), but this returns false. Such a pair denies access that could have been allowed; it never allows access that should have been denied. Grants without a */# adjacency — every ordinary shape, including a.#, a.*, a.#.b, # — are decided exactly.