Repository navigation
Add mapbox map-matching - #45
mattpodwysocki wants to merge 1 commit into
Conversation
bd00deb to
16e44ed
Compare
21ec4b4 to
232803a
Compare
16e44ed to
17ae5e4
Compare
Third of the Navigation-category APIs with no prior CLI coverage. Same shape as directions/isochrone (#43, #44): hand-authored into custom-openapi/ since openapi-specs has no spec for this API either, reusing ARG_NAME_OVERRIDES for the same profile-vs-global-flag collision (third row, not a third mechanism). Excludes POST, for the same documented reason directions route does: this spec format can't express "GET or POST, caller's choice" for one operationId, and the API's own POST exists specifically for a trace too long for a URL (~8100 bytes) — a real gap, not a design choice. Smoke-tested against production: a three-point San Francisco trace returned a real match with legs/steps/geometry, including a null tracepoint for a point too far from the road network to match — the documented shape for that case, not a bug. 486 tests, fmt and clippy clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
232803a to
6e045a1
Compare
zmofei
left a comment
There was a problem hiding this comment.
The command name does not match the design doc, and a few parameter descriptions differ from the Map Matching docs. I checked each one against the real API. Details inline.
| /// [`FLATTENED_SERVICES`] service correctly for free, because they all go | ||
| /// through `command()` rather than reconstructing the string themselves. | ||
| pub const FLATTENED_SERVICES: &[&str] = &["directions", "isochrone"]; | ||
| pub const FLATTENED_SERVICES: &[&str] = &["directions", "isochrone", "map-matching"]; |
There was a problem hiding this comment.
The design doc names this command mapbox map-match, not mapbox map-matching. Please rename it everywhere: the custom-openapi entry, the three tables in spec.rs, remedy.rs, docs, README, CHANGELOG and the command surface fixture. #48 will need the same change.
| index. Requires `--steps`. | ||
| schema: | ||
| type: string | ||
| example: "0,2" |
There was a problem hiding this comment.
The API wants waypoints separated by ;, not ,. With --waypoints 0,2 (the example here) it returns 422: "Waypoints must be a list of at least two indexes separated by ';'". Please change the example to 0;2 and say "semicolon-separated" in the description and in docs/commands.md. Also, --waypoints does not require --steps. The docs only say it is "most useful" with steps, and the API accepts it without them.
| # `PossibleValuesParser`, which accepts one value and would refuse | ||
| # `distance,duration`. Same reasoning as `directions.yaml`'s | ||
| # `annotations`. | ||
| - name: "annotations" |
There was a problem hiding this comment.
The docs limit some values to certain profiles, but the descriptions here do not say so: congestion/congestion_numeric work only with mapbox/driving-traffic, maxspeed only with driving and driving-traffic, and --linear-references (line 223) only with driving and driving-traffic. I checked: congestion on mapbox/driving returns all "unknown", and --linear-references on mapbox/walking returns a 422 that does not mention the profile. Please add these limits to the descriptions and docs/commands.md.
| schema: | ||
| type: string | ||
| enum: ["tomtom"] | ||
| - name: "depart_at" |
There was a problem hiding this comment.
Nit: the docs do not limit depart_at to mapbox/driving-traffic, and the API takes only three formats, not any ISO 8601. For example, 2030-01-01T08:00:00 returns 422. Maybe say "Departure time from the first coordinate" and list YYYY-MM-DDThh:mm, YYYY-MM-DDThh:mm:ssZ and YYYY-MM-DDThh:mm:ss±hh:mm.
Same stacking situation as #44 on #43. This reuses the flattening mechanism
(
spec::FLATTENED_SERVICES),ARG_NAME_OVERRIDES, and thepath_segment_for/UNESCAPED_PATH_PARAMSfix #43 introduces, since everyone of these Navigation APIs'
profilepath parameter hits the sameglobal-flag collision and needs the same free-form profile. Once #43 and
#44 merge in order, this should be retargeted to
main(gh pr edit --base main). Everything below is scoped to what this PR actually adds on top of#44.
What
mapbox map-matching, the third Navigation-category API with no priorCLI coverage. Same shape as #43/#44: hand-authored into
custom-openapi/since openapi-specs publishes no spec for it either.
No subcommand: like
mapbox directionsandmapbox isochrone, this APIhas one operation, so there's nothing a second word (the old
match)would disambiguate. Same shape
mapbox usagealready has.Snaps a noisy GPS trace to the road network and returns the route it most
likely followed, for driving (with or without live traffic), walking, or
cycling. One or more matched routes (more than one where the trace is
ambiguous enough to split), each with a
confidence, plus one tracepointper input coordinate (
nullfor one too far from any candidate to match atall).
Excluded on purpose: POST, for the same reason
directionsexcludesit. This spec format has no way to express "GET or POST, caller's choice"
for one operationId. The API's own POST exists specifically for a trace
too long for a URL (~8100 bytes), a real gap for a very long trace rather
than a design choice.
Routing profile is free-form here too
Same fix as #43 and #44: an earlier version of this command validated
profileagainst the four documented values client-side, via a clap enum.Some OEM accounts have additional profiles that aren't published, so that
validation would have broken this command for exactly the accounts that
most need it.
profileis now sent exactly as typed, and reaches the URLunescaped through
UNESCAPED_PATH_PARAMS(("map-matching", "profile")).Verification
Smoke-tested against production: a three-point San Francisco trace
returned a real match with
legs/steps/geometry, including anulltracepoint for a point deliberately placed too far from the road network to
match, the documented shape for that case, confirmed rather than assumed.
The bare
mapbox map-matchingcommand shape itself is also verified (nosubcommand accepted,
--schemareflects the new name).489 tests,
cargo fmt --checkandcargo clippy --all-targets -- -D warningsboth clean.🤖 Generated with Claude Code