1use setzer_model::asset::Asset;
4
5pub const MAX_IMAGE_BYTES: u64 = 100 * 1024 * 1024;
7
8pub fn unique_id(path: &str, ext: &str, assets: &[Asset]) -> String {
12 let base = path.rsplit(['/', '\\']).next().unwrap_or("image");
13 let stem = base.rsplit_once('.').map_or(base, |(s, _)| s);
14 let clean: String = stem
15 .chars()
16 .map(|c| {
17 if c.is_ascii_alphanumeric() || c == '-' || c == '_' {
18 c
19 } else {
20 '_'
21 }
22 })
23 .collect();
24 let clean = if clean.is_empty() {
25 "image".into()
26 } else {
27 clean
28 };
29 let mut id = format!("{clean}.{ext}");
30 let mut n = 2;
31 while assets.iter().any(|a| a.id == id) {
32 id = format!("{clean}-{n}.{ext}");
33 n += 1;
34 }
35 id
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn ids_are_sanitized_and_unique() {
44 let taken = vec![Asset::new("map.png", Vec::new())];
45 assert_eq!(unique_id("img/Karte 1.jpeg", "jpg", &[]), "Karte_1.jpg");
46 assert_eq!(unique_id(r"bilder\map.PNG", "png", &taken), "map-2.png");
47 assert_eq!(unique_id(".png", "png", &[]), "image.png");
48 assert!(Asset::is_valid_id(&unique_id("ü/ö ä", "gif", &[])));
49 }
50}