[Web]RouteOne compiled path pattern: static segments, ':name' (captures exactly one segment, percent-decoded), and a final '*name' (the — possibly empty — rest of the path). Trailing slashes normalize away (except root '/'); decoding happens per segment after splitting on '/', so an encoded %2F can never create a segment boundary.
var r = [Web]Route.of:'/users/:id/files/*rest'; r ~ '/users/7/files/a/b' "* -> true "* routes implement the ~ protocol; bind: extracts the captures r.bind:'/users/7/files/a/b' "* -> #{'id': '7' 'rest': 'a/b'}
':name' / '*name' -> 'name' (everything after the marker), rejecting an empty one.
Compile pattern into a route; a bad pattern (a non-final *splat, an empty parameter name) throws ValueError.
Path/pattern segments: split on '/', dropping the leading empty segment and a trailing one (trailing-slash normalization; '/' -> no segments).
Match path (query already stripped), binding params: a Map (possibly empty) on a match, nil otherwise. Path segments are percent-decoded before comparison and capture; a malformed escape throws ValueError (-> 400).
Two routes conflict when their shapes are identical — same kinds and the same static texts (param NAMES don't matter: '/a/:x' and '/a/:y' match exactly the same paths). Such a pair could tie at dispatch, so it throws at registration instead.
Compile pattern (via [Web]Route.of:). Each segment becomes a #( kindInt text ) pair: #(0 'users'), #(1 'id'), #(2 'rest').
The specificity vector: one of 0 (static) / 1 (:param) / 2 (*splat) per segment.
True when my kind vector sorts strictly before other's, position by position (static beats :param beats *splat). Two co-matching routes always differ somewhere — except an equal shape, which registration rejects; when one is a kind-prefix of the other (an exact route vs. one more trailing empty-matching *splat), the shorter — exact — route wins.
The pattern string as given.
Human rendering: the pattern.
Internal: the compiled #( kind text ) segment pairs.
The ~ match protocol: route ~ path (also composes with case:).