Skip to main content

stable_osstring_encoding/
lib.rs

1#![warn(missing_docs, clippy::all)]
2#![doc = include_str!("../readme.md")]
3
4
5
6#[cfg(not(any(unix, windows)))]
7compile_error!(
8	"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."
9);
10
11
12
13use std::{borrow::Cow, ffi::OsStr};
14
15
16
17/// Contains the implementation for unix builds, including Linux and Macos
18#[cfg(unix)]
19pub mod impl_unix;
20/// Contains the implementation for windows builds
21#[cfg(windows)]
22pub mod impl_windows;
23
24
25
26/// Defines the encoding width
27#[cfg(unix)]
28pub type EncodingWidth = u8;
29/// Defines the encoding width
30#[cfg(windows)]
31pub type EncodingWidth = u16;
32
33/// A simple alias for `Vec<EncodingWidth>`
34pub type StableOsString = Vec<EncodingWidth>;
35
36
37
38/// Converts an `OsString` or `OsStr` to an encoding that is stable across rust compiler versions
39pub trait ToStableEncoding {
40	/// Converts an `OsString` or `OsStr` to an encoding that is stable across rust compiler versions
41	fn to_stable_encoding(&self) -> StableOsString;
42}
43
44/// Converts an `OsString` from an encoding that is stable across rust compiler versions, bypassing data copies if possible
45pub trait IntoStableEncoding {
46	/// Converts an `OsString` from an encoding that is stable across rust compiler versions, bypassing data copies if possible
47	fn into_stable_encoding(self) -> StableOsString;
48}
49
50/// Converts an `OsString` from an encoding that is stable across rust compiler versions, bypassing data copies if possible
51pub trait FromStableEncoding {
52	/// Converts an `OsString` from an encoding that is stable across rust compiler versions, bypassing data copies if possible
53	///
54	/// # Safety
55	///
56	/// The given bytes must be compatible with the underlying of the platform's `OsStr` encoding (reminder: this crate only make it safe to pass data between different rust versions)
57	unsafe fn from_stable_encoding<'a>(encoded: impl Into<Cow<'a, [EncodingWidth]>>) -> Self;
58}
59
60
61
62impl<'a> IntoStableEncoding for Cow<'a, OsStr> {
63	fn into_stable_encoding(self) -> StableOsString {
64		match self {
65			Cow::Borrowed(os_str) => os_str.to_stable_encoding(),
66			Cow::Owned(os_string) => os_string.into_stable_encoding(),
67		}
68	}
69}
70
71
72
73#[cfg(test)]
74mod test {
75	use crate::{FromStableEncoding, IntoStableEncoding, ToStableEncoding};
76	use std::ffi::OsString;
77
78	#[test]
79	fn basics() {
80		let start = OsString::from("test");
81		let as_stable_1 = start.to_stable_encoding();
82		let as_stable_2 = start.into_stable_encoding();
83		assert_eq!(as_stable_1, as_stable_2);
84
85		let as_stable_1 = &*as_stable_1; // make sure &[EncodingWidth] can be given to from_stable_encoding()
86
87		let as_os_string_1 = unsafe { OsString::from_stable_encoding(as_stable_1) };
88		let as_os_string_2 = unsafe { OsString::from_stable_encoding(as_stable_2) };
89		assert_eq!(as_os_string_1, as_os_string_2);
90
91		let as_str = as_os_string_1.to_str();
92		assert_eq!(as_str, Some("test"));
93	}
94}