parseDeepLink function

SdkResult<DeepLinkCommand> parseDeepLink(
  1. Uri uri,
  2. List<DeepLinkRoute> routes, {
  3. int maxLength = 2048,
})

Pure parser — no I/O, no singletons — matches uri against routes in order, first match wins. Rejects (never throws) on: a URI longer than maxLength (guards against an oversized query string), a scheme/host not in any route, or a path that doesn't match any route's shape.

Implementation

SdkResult<DeepLinkCommand> parseDeepLink(
  Uri uri,
  List<DeepLinkRoute> routes, {
  int maxLength = 2048,
}) {
  if (uri.toString().length > maxLength) {
    return const SdkFailure(
      kind: SdkErrorKind.validation,
      message: 'Deep link exceeds max length',
    );
  }
  for (final route in routes) {
    if (route.scheme != uri.scheme) continue;
    if (route.host != null && route.host != uri.host) continue;
    final segments = uri.pathSegments;
    if (segments.length != route.pathSegments.length) continue;

    final params = <String, String>{};
    var matched = true;
    for (var i = 0; i < segments.length; i++) {
      final pattern = route.pathSegments[i];
      if (pattern.startsWith(':')) {
        params[pattern.substring(1)] = segments[i];
      } else if (pattern != segments[i]) {
        matched = false;
        break;
      }
    }
    if (!matched) continue;

    // BUG-50: query params must never override a path param of the same
    // name (see the class doc comment above) — `putIfAbsent`, not `addAll`.
    uri.queryParameters.forEach((k, v) => params.putIfAbsent(k, () => v));
    return SdkSuccess(
      DeepLinkCommand(type: route.commandType, params: params, raw: uri),
    );
  }
  return SdkFailure(
    kind: SdkErrorKind.validation,
    message: 'No route matches $uri',
  );
}