Skip to main content

path_rs/
utf8.rs

1//! UTF-8 helpers for paths.
2//!
3//! Internal filesystem representation remains `Path` / `PathBuf` / `OsStr`.
4//! Never round-trip a path through lossy UTF-8 for filesystem operations.
5
6use crate::error::PathError;
7use std::borrow::Cow;
8use std::path::Path;
9
10/// Convert a path to a UTF-8 string slice, or error if it is not valid UTF-8.
11///
12/// # Filesystem access
13///
14/// **No.**
15pub fn path_to_utf8(path: &Path) -> Result<&str, PathError> {
16    path.to_str().ok_or(PathError::NotUtf8)
17}
18
19/// Lossy UTF-8 conversion suitable for logs and UI only.
20///
21/// **Never** use the result as a filesystem path for further I/O.
22///
23/// # Filesystem access
24///
25/// **No.**
26pub fn path_to_string_lossy(path: &Path) -> Cow<'_, str> {
27    path.to_string_lossy()
28}
29
30/// Produce a Unicode-normalized logical key for comparison purposes.
31///
32/// Requires the `unicode` feature. The result must **not** be used as a filesystem path.
33///
34/// Normalization form: NFC.
35#[cfg(feature = "unicode")]
36pub fn logical_path_key(path: &Path) -> String {
37    use unicode_normalization::UnicodeNormalization;
38    path.to_string_lossy().nfc().collect::<String>()
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44    use std::path::Path;
45
46    #[test]
47    fn utf8_ok() {
48        assert_eq!(path_to_utf8(Path::new("foo/bar")).unwrap(), "foo/bar");
49    }
50}