1use std::{borrow::Cow, ffi::OsStr, path::Path};
2
3pub fn precompose(s: Cow<'_, str>) -> Cow<'_, str> {
7 use unicode_normalization::UnicodeNormalization;
8 if s.as_ref().nfc().cmp(s.as_ref().chars()).is_eq() {
9 s
10 } else {
11 Cow::Owned(s.as_ref().nfc().collect())
12 }
13}
14
15pub fn decompose(s: Cow<'_, str>) -> Cow<'_, str> {
19 use unicode_normalization::UnicodeNormalization;
20 if s.as_ref().nfd().cmp(s.as_ref().chars()).is_eq() {
21 s
22 } else {
23 Cow::Owned(s.as_ref().nfd().collect())
24 }
25}
26
27pub fn precompose_path(path: Cow<'_, Path>) -> Cow<'_, Path> {
31 match path.to_str() {
32 None => path,
33 Some(maybe_decomposed) => match precompose(maybe_decomposed.into()) {
34 Cow::Borrowed(_) => path,
35 Cow::Owned(precomposed) => Cow::Owned(precomposed.into()),
36 },
37 }
38}
39
40pub fn precompose_os_string(name: Cow<'_, OsStr>) -> Cow<'_, OsStr> {
44 match name.to_str() {
45 None => name,
46 Some(maybe_decomposed) => match precompose(maybe_decomposed.into()) {
47 Cow::Borrowed(_) => name,
48 Cow::Owned(precomposed) => Cow::Owned(precomposed.into()),
49 },
50 }
51}
52
53#[cfg(feature = "bstr")]
57pub fn precompose_bstr(s: Cow<'_, bstr::BStr>) -> Cow<'_, bstr::BStr> {
58 use bstr::ByteSlice;
59 match s.to_str().ok() {
60 None => s,
61 Some(maybe_decomposed) => match precompose(maybe_decomposed.into()) {
62 Cow::Borrowed(_) => s,
63 Cow::Owned(precomposed) => Cow::Owned(precomposed.into()),
64 },
65 }
66}