Skip to main content

pacenotes_shared/
download_path.rs

1/// Takes a `game/directory/name` apart, the inverse of
2/// `PackageInfo::download_path`; only the first two `/` separate, since the
3/// name is itself a path. `None` unless every part is valid.
4pub fn split_download_path(path: &str) -> Option<(&str, &str, &str)> {
5    let (game, rest) = path.split_once('/')?;
6    let (directory, name) = rest.split_once('/')?;
7    if !crate::valid_id(game) || !crate::valid_id(directory) || !crate::valid_name(name) {
8        return None;
9    }
10    Some((game, directory, name))
11}
12
13/// The first segment of the name in a `game/directory/name`.
14pub fn category_of_download_path(path: &str) -> Option<&str> {
15    let (_, _, name) = split_download_path(path)?;
16    Some(name.split('/').next().unwrap_or(name))
17}
18
19#[cfg(test)]
20mod tests {
21    #[test]
22    fn a_download_path_comes_apart_the_way_it_went_together() {
23        let path = crate::fixtures::package(crate::PUBLIC_DIR, "codriver/polish/male/Kamil")
24            .download_path();
25        assert_eq!(
26            super::split_download_path(&path),
27            Some(("rbr", "public", "codriver/polish/male/Kamil"))
28        );
29        assert_eq!(
30            super::category_of_download_path(&path),
31            Some(crate::CATEGORY_CODRIVER)
32        );
33        assert_eq!(
34            super::category_of_download_path("rbr/public/language/polish"),
35            Some(crate::CATEGORY_LANGUAGE)
36        );
37    }
38
39    /// Half a package would have a caller look up, delete or download the wrong thing.
40    #[test]
41    fn a_malformed_download_path_parses_to_nothing() {
42        for bad in [
43            "",
44            "rbr",
45            "rbr/public",
46            "rbr/public/",
47            "rbr/public/../escape",
48            "RBR/public/x",
49            "rbr/Public/x",
50            "rbr/public/a\\b",
51            "rbr/public/x\nkey=evil",
52        ] {
53            assert_eq!(super::split_download_path(bad), None, "{bad:?}");
54        }
55    }
56}