use crate::{PathError, PathResult};
use encoding_rs::{UTF_8, UTF_16LE, WINDOWS_1252};
#[derive(Debug, Clone, Copy)]
pub struct UnicodeHandler;
impl UnicodeHandler {
#[must_use]
pub fn detect_encoding(bytes: &[u8]) -> &'static encoding_rs::Encoding {
if String::from_utf8(bytes.to_vec()).is_ok() {
return UTF_8;
}
if bytes.len() >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE {
return UTF_16LE;
}
WINDOWS_1252
}
pub fn convert_to_utf8(bytes: &[u8]) -> PathResult<String> {
let encoding = Self::detect_encoding(bytes);
let (decoded, _, had_errors) = encoding.decode(bytes);
if had_errors {
return Err(PathError::encoding_error(
"Encoding conversion encountered errors",
));
}
Ok(decoded.into_owned())
}
pub fn convert_from_utf8(
text: &str,
target_encoding: &'static encoding_rs::Encoding,
) -> PathResult<Vec<u8>> {
let (encoded, _, had_errors) = target_encoding.encode(text);
if had_errors {
return Err(PathError::encoding_error(
"Encoding conversion encountered errors",
));
}
Ok(encoded.into_owned())
}
#[must_use]
pub fn normalize_windows_path(path: &str) -> String {
let mut result = path.to_string();
let invalid_chars = ['<', '>', ':', '"', '|', '?', '*'];
for c in invalid_chars {
result = result.replace(c, "_");
}
result = result.chars().filter(|c| !c.is_control()).collect();
result
}
#[must_use]
pub fn normalize_unix_path(path: &str) -> String {
let mut result = path.to_string();
result = result.replace('\0', "");
result = result.chars().filter(|c| !c.is_control()).collect();
result
}
pub fn convert_path_encoding(
path: &str,
from: &'static encoding_rs::Encoding,
to: &'static encoding_rs::Encoding,
) -> PathResult<String> {
if from == to {
return Ok(path.to_string());
}
let bytes = from.encode(path).0;
let (decoded, _, had_errors) = to.decode(&bytes);
if had_errors {
return Err(PathError::encoding_error("Path encoding conversion failed"));
}
Ok(decoded.into_owned())
}
}