pacenotes_shared/
download_path.rs1pub 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
13pub 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 #[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}