Expand description
Turn messy track names into structured data: artists with roles, remixes and versions, junk, and whole tracklists.
trackparse is driven by a written spec. Behaviour is defined by SPEC.md and its shared
fixtures. This crate passes every shared fixture, and for every fixture input its output is
byte-identical to the JavaScript (npm trackparse) and Python (PyPI trackparse) packages.
Rule IDs such as R6.2 in these docs refer to the spec.
- User documentation: https://4matic.github.io/trackparse/
- The spec: https://4matic.github.io/trackparse/reference/spec/
§Single tracks
parse takes any string and returns a ParsedTrack. It never panics and never returns
an error: what it recognises goes into a field, what it does not stays in the title.
use trackparse::{parse, ArtistRole, JunkKind, VersionType};
let track = parse("Noisia feat. Foreign Beggars - Shellshock (Rockwell Remix) [Official Video]");
assert_eq!(track.artists[0].name, "Noisia");
assert_eq!(track.artists[1].name, "Foreign Beggars");
assert_eq!(track.artists[1].role, ArtistRole::Featured);
assert_eq!(track.title, "Shellshock");
assert_eq!(track.full_title, "Shellshock (Rockwell Remix)");
assert_eq!(track.versions[0].version_type, VersionType::Remix);
assert_eq!(track.versions[0].artists[0].name, "Rockwell");
assert_eq!(track.junk[0].kind, JunkKind::Video);parse_with takes ParseOptions; a Parser keeps resolved options for many calls.
parse_artists splits a credit string, format_track writes a track back as a string,
normalize() cleans a string without parsing it, and all_artists lists every credited
name, remixers included.
use trackparse::{format_track_with, parse_with, FeatPlacement, FormatOptions, ParseOptions};
let options = ParseOptions::new().known_artists(["Chase & Status"]);
let track = parse_with("Chase & Status - Blind Faith ft. Liam Bailey", &options);
assert_eq!(track.artists.len(), 2);
let format = FormatOptions::new().feat(FeatPlacement::Artist);
assert_eq!(format_track_with(&track, &format), "Chase & Status ft. Liam Bailey - Blind Faith");§Tracklists
The tracklist module reads a whole pasted tracklist: one entry per line, with its time,
its kind and the parsed track, plus warnings about the times. tracklist::apply_edits
rewrites times and lines without touching anything else.
use trackparse::tracklist::{apply_edits, parse_tracklist, Edit, WarningCode};
let text = "00:00 Noisia - Stigma\n03:45 Phace & Misanthrop - Desert Orgy\n02:10 Mefjus - Suicide Bassline";
let list = parse_tracklist(text);
assert_eq!(list.stats.tracks, 3);
assert_eq!(list.entries[1].time.as_ref().unwrap().seconds, 225.0);
assert_eq!(list.entries[1].track.as_ref().unwrap().title, "Desert Orgy");
assert_eq!(list.warnings[0].code, WarningCode::TimeOutOfOrder);
let fixed = apply_edits(text, &[Edit::sort_by_time()]);
assert_eq!(
fixed.text,
"00:00 Noisia - Stigma\n02:10 Mefjus - Suicide Bassline\n03:45 Phace & Misanthrop - Desert Orgy"
);§JSON
Fields are snake_case in Rust. to_json() on every output type writes the spec’s JSON form:
camelCase keys (fullTitle, unknownArtist), every key present, in the schema’s order. It is
the same text the JavaScript and Python packages produce, and needs no dependency.
let artists = trackparse::parse_artists("Noisia & Phace");
assert_eq!(
artists[1].to_json(),
r#"{"name":"Phace","role":"primary","joiner":"&","source":"artist"}"#
);With the serde feature the output types implement Serialize and Deserialize with the
same keys, so serde_json::to_string(&track) gives the text of track.to_json(). The
options and tracklist::Edit implement both traits too. Numbers are written as
to_json() writes them. The exceptions are numbers no parse result contains: seconds from
0.000001 up to 0.00001 (and, with older serde_json releases, of 1e21 and more) in an
Edit or an option built by hand, which serde_json writes in its own float notation
(1e-6 for 0.000001). Non-finite seconds are written as null, as by to_json(), and
null reads back as NaN. Keyword maps are written without repeated keys (the last value
wins, as in a JS object).
§Guarantees
- Total: any
&strgives a result. No panics, noResult(R0.8). - No regular expressions and no backtracking: the scanners make a bounded number of passes over the input. A 10,000-code-point string parses in a few milliseconds, and the test suite checks that repeated hostile fragments scale far below quadratic.
- No
unsafe. One dependency (unicode-normalization);serdeonly with the feature. - The Unicode tables the rules depend on (letters, uppercase letters, lowercase mapping) are compiled in, so the output does not change with the compiler version.
- NFC and NFD (R1, R0.4) come from
unicode-normalizationand follow that crate’s Unicode version: 0.1.26, the minimum this crate accepts, has the Unicode 18 tables. The JavaScript reference normalizes with its runtime’s tables (Unicode 17 on Node 24), so a string with one of the 32 combining marks added in Unicode 18 can come out in another mark order than it does there. Text without those marks is not affected.
Modules§
- json
- A small JSON value with a reader and a writer. The crate has no JSON dependency: this is what
to_json()writes with, and what the fixtures and the cross-port diff read. - tracklist
- Multi-line tracklists (SPEC R13):
parse_tracklistandapply_edits.
Structs§
- Artist
- One credited artist.
- Flags
- Yes/no facts about the track.
- Format
Options - Options of
format_track_with(R11). - Junk
- A fragment that says nothing about the track:
Official Video,HD,Free Download. It is taken out of the title and kept here (the parser extracts, it does not delete). - Keyword
Options - Extra vocabulary, added to the built-in word lists (R12). Keys are matched with ASCII lowercasing.
- Parse
Options - Options of
parse_with,parse_artists_withandParser(R12). The default is whatparseuses. - Parsed
Track - The result of
parse: everything recognised in one track string. - Parser
- A parser with its options resolved and its vocabulary tables built once (
createParserin JavaScript,create_parserin Python). Use it to parse many strings with the same options. It isSend + Sync, and cloning it is cheap (the tables are shared). - Position
- A track number in front of the string (R4.2).
- Timestamp
- A cue time in front of a single track string (R4.1), in whole seconds.
- Unknown
Name - The error of
FromStron the crate’s enums: the string is not one of the spec’s names. - Version
- One version of the track: a remix, an edit, a live take, a remaster (R5, R8).
Enums§
- Artist
Role - What an artist did on the track (R7).
- Artist
Source - Where in the string an artist was found: the artist side, the title side, or a version group.
- Feat
Placement - Where
format_track_withwrites featured artists (R11.2). - Joiner
Style - Joiners as written, or mapped to their canonical form (R11.5).
- Junk
Kind - What kind of noise a junk fragment is (R5).
- Mode
- The mode a string was parsed in (R2).
Tracklistis only used when asked for (R13.6);autonever resolves to it. - Mode
Option - The mode to parse in (R2).
Autopicks clean, youtube or filename from the string itself, never tracklist. - Split
And - When the word
andsplits a credit list (R7.3).&and the other joiners always split. - Version
Delimiter - How a version was written: in a bracket group, or after a dash.
- Version
Type - The type of a version (R5): remix, edit, live, remaster and so on.
- Versions
Option - Whether
format_track_withwrites the versions (R11.3). - Warning
- A warning of the single-track parser: the result is a guess the caller may want to check.
Constants§
- SPEC_
VERSION - The version of the spec this crate implements.
Traits§
- ToJson
- Conversion to the spec’s JSON form (camelCase keys, every key present, schema order).
Functions§
- all_
artists - All credited names: the track’s artists plus every version’s remixers, deduped (R0.4 key).
- format_
track - Render a parsed track back to a string (R11) with the default format options.
- format_
track_ with - Render a parsed track back to a string (R11).
- normalize
- Normalize a track string (R1): NFC, ASCII brackets, quotes and dashes, invisible characters removed, whitespace collapsed. Idempotent.
- parse
- Parse one track string with the default options (mode
auto). - parse_
artists - Split a credit string into artists (R10).
- parse_
artists_ with parse_artistswith options (known_artists,split_and,keywords).- parse_
with - Parse one track string with options (R12).