1use crate::displayed_item_tree::VisibleItemIndex;
3use camino::Utf8PathBuf;
4#[cfg(not(target_arch = "wasm32"))]
5use std::path::{Path, PathBuf};
6
7pub fn uint_idx_to_alpha_idx(idx: VisibleItemIndex, nvariables: usize) -> String {
12 let width = usize::try_from(nvariables.ilog(16)).unwrap() + 1;
16 format!("{:0width$x}", idx.0)
17 .chars()
18 .map(|c| match c {
19 '0' => 'a',
20 '1' => 'b',
21 '2' => 'c',
22 '3' => 'd',
23 '4' => 'e',
24 '5' => 'f',
25 '6' => 'g',
26 '7' => 'h',
27 '8' => 'i',
28 '9' => 'j',
29 'a' => 'k',
30 'b' => 'l',
31 'c' => 'm',
32 'd' => 'n',
33 'e' => 'o',
34 'f' => 'p',
35 _ => '?',
36 })
37 .collect()
38}
39
40pub fn alpha_idx_to_uint_idx(idx: String) -> Option<VisibleItemIndex> {
42 let mapped = idx
43 .chars()
44 .map(|c| match c {
45 'a' => '0',
46 'b' => '1',
47 'c' => '2',
48 'd' => '3',
49 'e' => '4',
50 'f' => '5',
51 'g' => '6',
52 'h' => '7',
53 'i' => '8',
54 'j' => '9',
55 'k' => 'a',
56 'l' => 'b',
57 'm' => 'c',
58 'n' => 'd',
59 'o' => 'e',
60 'p' => 'f',
61 _ => '?',
62 })
63 .collect::<String>();
64 usize::from_str_radix(&mapped, 16)
65 .ok()
66 .map(VisibleItemIndex)
67}
68
69#[cfg(not(target_arch = "wasm32"))]
73pub fn search_upward(
74 start: impl AsRef<Path>,
75 end: impl AsRef<Path>,
76 item: impl AsRef<Path>,
77) -> Vec<PathBuf> {
78 start
79 .as_ref()
80 .ancestors()
81 .take_while(|p| p.starts_with(end.as_ref()))
82 .map(|p| p.join(&item))
83 .filter(|p| p.try_exists().is_ok_and(std::convert::identity))
84 .collect()
85}
86
87pub fn get_multi_extension_from_filename(filename: &str) -> Option<String> {
88 filename
89 .as_bytes()
90 .iter()
91 .position(|&c| c == b'.')
92 .map(|pos| {
93 let iter = filename.chars().skip(pos + 1);
94 iter.collect::<String>()
95 })
96}
97
98pub fn get_multi_extension(path: &Utf8PathBuf) -> Option<String> {
102 if let Some(filename) = path.file_name() {
104 return get_multi_extension_from_filename(filename);
105 }
106 None
107}