#![warn(missing_docs, clippy::all)]
#![doc = include_str!("../readme.md")]
#[cfg(not(any(unix, windows)))]
compile_error!(
"This crate currently only supports Windows and Unix (Linux and Macos). Adding support for your platform is likely very easy, please consider opening an issue for it in \"stable-osstring-encoding\"'s issue tracker."
);
use std::{
borrow::Cow,
ffi::OsString,
path::{Path, PathBuf},
};
#[cfg(unix)]
pub mod impl_unix;
#[cfg(windows)]
pub mod impl_windows;
#[cfg(unix)]
pub type EncodingWidth = u8;
#[cfg(windows)]
pub type EncodingWidth = u16;
pub type StableOsString = Vec<EncodingWidth>;
pub trait ToStableEncoding {
fn to_stable_encoding(&self) -> StableOsString;
}
pub trait IntoStableEncoding {
fn into_stable_encoding(self) -> StableOsString;
}
pub trait FromStableEncoding {
unsafe fn from_stable_encoding<'a>(encoded: impl Into<Cow<'a, [EncodingWidth]>>) -> Self;
}
impl ToStableEncoding for Path {
fn to_stable_encoding(&self) -> StableOsString {
self.as_os_str().to_stable_encoding()
}
}
impl ToStableEncoding for PathBuf {
fn to_stable_encoding(&self) -> StableOsString {
self.as_os_str().to_stable_encoding()
}
}
impl IntoStableEncoding for PathBuf {
fn into_stable_encoding(self) -> StableOsString {
self.into_os_string().to_stable_encoding()
}
}
impl FromStableEncoding for PathBuf {
unsafe fn from_stable_encoding<'a>(encoded: impl Into<Cow<'a, [EncodingWidth]>>) -> Self {
unsafe { PathBuf::from(OsString::from_stable_encoding(encoded)) }
}
}
impl<'a, T> IntoStableEncoding for Cow<'a, T>
where
T: ToStableEncoding + ToOwned,
<T as ToOwned>::Owned: IntoStableEncoding,
{
fn into_stable_encoding(self) -> StableOsString {
match self {
Cow::Borrowed(v) => v.to_stable_encoding(),
Cow::Owned(v) => v.into_stable_encoding(),
}
}
}
#[cfg(test)]
mod test {
use crate::{FromStableEncoding, IntoStableEncoding, ToStableEncoding};
use std::{ffi::OsString, path::PathBuf};
#[test]
fn basics() {
let start = OsString::from("test");
let as_stable_1 = start.to_stable_encoding();
let as_stable_2 = start.into_stable_encoding();
assert_eq!(as_stable_1, as_stable_2);
let as_stable_1 = &*as_stable_1;
let as_os_string_1 = unsafe { OsString::from_stable_encoding(as_stable_1) };
let as_os_string_2 = unsafe { OsString::from_stable_encoding(as_stable_2) };
assert_eq!(as_os_string_1, as_os_string_2);
let as_str = as_os_string_1.to_str();
assert_eq!(as_str, Some("test"));
}
#[test]
fn path_buf() {
let start = PathBuf::from(OsString::from("test"));
let as_stable_1 = start.to_stable_encoding();
let as_stable_2 = start.into_stable_encoding();
assert_eq!(as_stable_1, as_stable_2);
let as_stable_1 = &*as_stable_1;
let as_os_string_1 = unsafe { PathBuf::from_stable_encoding(as_stable_1) };
let as_os_string_2 = unsafe { PathBuf::from_stable_encoding(as_stable_2) };
assert_eq!(as_os_string_1, as_os_string_2);
let as_str = as_os_string_1.to_str();
assert_eq!(as_str, Some("test"));
}
}