1use std::path::Path;
8
9pub fn extension_of(file_name: &str) -> Option<&str> {
11 Path::new(file_name)
12 .extension()
13 .and_then(|extension| extension.to_str())
14 .filter(|extension| !extension.is_empty())
15}
16
17pub fn with_extension(file_name: Option<&str>, extension: &str) -> Option<String> {
20 let file_name = file_name?;
21 Some(match extension_of(file_name) {
22 Some(_) => file_name.to_string(),
23 None => format!("{file_name}.{extension}"),
24 })
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30
31 #[test]
32 fn an_extension_is_only_read_when_it_is_present() {
33 assert_eq!(extension_of("a.png"), Some("png"));
34 assert_eq!(extension_of("dir/a.webp"), Some("webp"));
35 assert_eq!(extension_of("a"), None);
36 assert_eq!(extension_of("a."), None);
37 }
38
39 #[test]
40 fn a_missing_extension_is_appended() {
41 assert_eq!(with_extension(None, "webp"), None);
42 assert_eq!(with_extension(Some("a"), "webp").as_deref(), Some("a.webp"));
43 assert_eq!(
44 with_extension(Some("a.png"), "webp").as_deref(),
45 Some("a.png")
46 );
47 }
48}