Skip to main content

Crate blazingly_aasa

Crate blazingly_aasa 

Source
Expand description

Apple Associated Domains semantics for Rust and WebAssembly.

blazingly-aasa parses, validates, matches, explains, and compares apple-app-site-association files. It is a semantic engine, not a fetcher: it never touches the network, never opens an .ipa, and never claims to know what a device will do. Give it bytes and explicit context, and it tells you exactly what the document says.

§Three separate questions

  1. Is this parseable? AasaDocument::parse fails only on invalid JSON, a non-object root, or an oversized payload.
  2. Is this sane? CompiledAasa::validate returns a ValidationReport of stable, machine-readable DiagnosticCodes rather than a single yes/no.
  3. Does this URL match? CompiledAasa::match_url returns MatchDecision::Match, MatchDecision::Exclude, or MatchDecision::NoMatch — with a trace explaining why.

A URL that does not match is not an error, and neither is one that is excluded. Both are answers.

§Matching a URL

use blazingly_aasa::{CompiledAasa, MatchDecision};

let bytes = br#"{
  "applinks": {
    "details": [{
      "appIDs": ["ABCDE12345.com.example.app"],
      "components": [
        { "/": "/help/website/*", "exclude": true },
        { "/": "/help/*", "?": { "articleNumber": "????" } }
      ]
    }]
  }
}"#;

let aasa = CompiledAasa::parse(bytes)?;
let app = "ABCDE12345.com.example.app";

let hit = aasa.match_url("example.com", app, "https://example.com/help/1?articleNumber=4815")?;
assert_eq!(hit.decision, MatchDecision::Match);

let blocked = aasa.match_url("example.com", app, "https://example.com/help/website/faq")?;
assert_eq!(blocked.decision, MatchDecision::Exclude);

// Three characters, not four: the query predicate rejects it.
let miss = aasa.match_url("example.com", app, "https://example.com/help/1?articleNumber=481")?;
assert_eq!(miss.decision, MatchDecision::NoMatch);

§Explaining a decision

Every result formats itself into something you can paste into a bug report:

let result = aasa.match_url("example.com", "A.b", "https://example.com/sell/42")?;
println!("{result}");

§Comparing two files

CompiledAasa::semantic_diff compares behaviour rather than text, so moving caseSensitive from every component up into defaults reports no change, while reordering two rules does:

use blazingly_aasa::CompiledAasa;

let spelled_out = CompiledAasa::parse(br#"{"applinks":{"details":[{
    "appIDs": ["A.b"],
    "components": [{ "/": "/buy/*", "caseSensitive": false }]
}]}}"#)?;

let refactored = CompiledAasa::parse(br#"{"applinks":{"details":[{
    "appIDs": ["A.b"],
    "defaults": { "caseSensitive": false },
    "components": [{ "/": "/buy/*" }]
}]}}"#)?;

assert!(spelled_out.semantic_diff(&refactored).is_equivalent());
assert!(!spelled_out.structural_equal(&refactored));

§What this crate will not do

It does not fetch .well-known/apple-app-site-association, talk to Apple’s CDN, read entitlements out of a signed binary, or model device state. Those belong in the tools that use this crate. See docs/parity.md for the behaviours that are verified against Apple’s documentation and the ones that are still open questions.

Structs§

AasaDiff
The result of comparing two documents.
AasaDocument
A parsed apple-app-site-association document.
AppLinkDetail
One entry of applinks.details.
AppLinks
The applinks section.
AppService
A service that is configured with a flat list of app identifiers.
CompiledAasa
A document normalised for matching, explaining, and comparing.
ComponentRule
One entry of a components array.
ComponentTrace
One component comparison inside a rule.
DetailTrace
One applinks.details entry considered during matching.
Diagnostic
A single validation finding, anchored at a location inside the document.
EffectiveDefaults
The effective pattern-matching settings for one rule, after resolving the defaults hierarchy.
EffectiveRule
A rule reduced to exactly what decides matching.
MatchDefaults
Pattern-matching defaults, which may appear at the domain and app level.
MatchResult
The result of matching one URL for one application identifier.
MatchTrace
The full record of a match attempt.
ParseError
A failure to parse an apple-app-site-association payload.
ParseOptions
Limits applied while parsing.
PatternSyntaxError
A pattern that could not be compiled.
RuleTrace
One rule evaluation.
UrlError
A URL that could not be split into the components required for matching.
UrlParts
The pieces of a URL that Associated Domains matching cares about.
ValidationReport
The result of validating a document.
WildcardPattern
A compiled Apple URL-component pattern.

Enums§

ComponentReason
Why one component matched or failed.
DiagnosticCode
A stable, machine-readable identifier for a validation finding.
EffectiveQuery
A ? constraint reduced to its comparable form.
Error
The crate-wide error type.
MatchDecision
The outcome of matching a URL against a document.
ParseErrorKind
Why an apple-app-site-association payload could not be turned into a document.
QueryPredicate
One entry of a ? dictionary.
QueryRule
The ? key, which Apple allows to be either a pattern or a dictionary of predicates.
SemanticChange
One semantic difference between two documents.
Service
An Associated Domains service.
Severity
How seriously to take a diagnostic.
StopReason
Why matching stopped where it did.
UrlComponent
Which part of the URL a component trace refers to.

Constants§

DEFAULT_CASE_SENSITIVE
Apple’s documented default: patterns are case-sensitive.
DEFAULT_PERCENT_ENCODED
Apple’s documented default: patterns are written percent-encoded.
ISO_TABLE_SOURCE
The Foundation release the $(region) and $(lang) tables were generated from.

Functions§

diff
Parses both documents and compares them semantically.
match_url
Parses and matches in one call.
percent_decode
Percent-decodes input, leaving invalid escapes untouched.
split_app_id
Splits ABCDE12345.com.example.app into its application identifier prefix and bundle identifier.
strip_leading_slash
The same path without its leading slash, when it has one to spare.
trim_path
A path with any trailing run of slashes removed.
validate
Parses and validates in one call.

Type Aliases§

Result
Convenience alias used across the crate.