From 8041194d36cca54155bdb03438d6cabd7c85141b Mon Sep 17 00:00:00 2001 From: kaivol Date: Fri, 15 Apr 2022 16:40:25 +0200 Subject: [PATCH] Added conversions between HSTRING and OsStr/OsString (#1693) --- crates/libs/windows/src/core/hstring.rs | 121 ++++++++++++++++++++++++ crates/tests/core/tests/hstrings.rs | 49 ++++++++++ 2 files changed, 170 insertions(+) diff --git a/crates/libs/windows/src/core/hstring.rs b/crates/libs/windows/src/core/hstring.rs index 810b184b69..10b96d7779 100644 --- a/crates/libs/windows/src/core/hstring.rs +++ b/crates/libs/windows/src/core/hstring.rs @@ -48,6 +48,11 @@ impl HSTRING { alloc::string::String::from_utf16_lossy(self.as_wide()) } + /// Get the contents of this `HSTRING` as a OsString. + pub fn to_os_string(&self) -> std::ffi::OsString { + std::os::windows::ffi::OsStringExt::from_wide(self.as_wide()) + } + /// Clear the contents of the string and free the memory if `self` holds the /// last reference to the string data. pub fn clear(&mut self) { @@ -164,6 +169,24 @@ impl core::convert::From<&alloc::string::String> for HSTRING { } } +impl core::convert::From<&std::ffi::OsStr> for HSTRING { + fn from(value: &std::ffi::OsStr) -> Self { + unsafe { Self::from_wide_iter(std::os::windows::ffi::OsStrExt::encode_wide(value), value.len() as u32) } + } +} + +impl core::convert::From for HSTRING { + fn from(value: std::ffi::OsString) -> Self { + value.as_os_str().into() + } +} + +impl core::convert::From<&std::ffi::OsString> for HSTRING { + fn from(value: &std::ffi::OsString) -> Self { + value.as_os_str().into() + } +} + impl PartialEq for HSTRING { fn eq(&self, other: &Self) -> bool { *self.as_wide() == *other.as_wide() @@ -242,6 +265,78 @@ impl PartialEq<&HSTRING> for alloc::string::String { } } +impl PartialEq for HSTRING { + fn eq(&self, other: &std::ffi::OsString) -> bool { + *self == **other + } +} + +impl PartialEq for &HSTRING { + fn eq(&self, other: &std::ffi::OsString) -> bool { + **self == **other + } +} + +impl PartialEq<&std::ffi::OsString> for HSTRING { + fn eq(&self, other: &&std::ffi::OsString) -> bool { + *self == ***other + } +} + +impl PartialEq for HSTRING { + fn eq(&self, other: &std::ffi::OsStr) -> bool { + self.as_wide().iter().copied().eq(std::os::windows::ffi::OsStrExt::encode_wide(other)) + } +} + +impl PartialEq for &HSTRING { + fn eq(&self, other: &std::ffi::OsStr) -> bool { + **self == *other + } +} + +impl PartialEq<&std::ffi::OsStr> for HSTRING { + fn eq(&self, other: &&std::ffi::OsStr) -> bool { + *self == **other + } +} + +impl PartialEq for std::ffi::OsStr { + fn eq(&self, other: &HSTRING) -> bool { + *other == *self + } +} + +impl PartialEq for &std::ffi::OsStr { + fn eq(&self, other: &HSTRING) -> bool { + *other == **self + } +} + +impl PartialEq<&HSTRING> for std::ffi::OsStr { + fn eq(&self, other: &&HSTRING) -> bool { + **other == *self + } +} + +impl PartialEq for std::ffi::OsString { + fn eq(&self, other: &HSTRING) -> bool { + *other == **self + } +} + +impl PartialEq for &std::ffi::OsString { + fn eq(&self, other: &HSTRING) -> bool { + *other == ***self + } +} + +impl PartialEq<&HSTRING> for std::ffi::OsString { + fn eq(&self, other: &&HSTRING) -> bool { + **other == **self + } +} + impl<'a> core::convert::TryFrom<&'a HSTRING> for alloc::string::String { type Error = alloc::string::FromUtf16Error; @@ -258,6 +353,18 @@ impl core::convert::TryFrom for alloc::string::String { } } +impl<'a> core::convert::From<&'a HSTRING> for std::ffi::OsString { + fn from(hstring: &HSTRING) -> Self { + hstring.to_os_string() + } +} + +impl core::convert::From for std::ffi::OsString { + fn from(hstring: HSTRING) -> Self { + Self::from(&hstring) + } +} + #[cfg(feature = "alloc")] impl<'a> IntoParam<'a, HSTRING> for &str { fn into_param(self) -> Param<'a, HSTRING> { @@ -272,6 +379,20 @@ impl<'a> IntoParam<'a, HSTRING> for alloc::string::String { } } +#[cfg(feature = "alloc")] +impl<'a> IntoParam<'a, HSTRING> for &std::ffi::OsStr { + fn into_param(self) -> Param<'a, HSTRING> { + Param::Owned(self.into()) + } +} + +#[cfg(feature = "alloc")] +impl<'a> IntoParam<'a, HSTRING> for std::ffi::OsString { + fn into_param(self) -> Param<'a, HSTRING> { + Param::Owned(self.into()) + } +} + const REFERENCE_FLAG: u32 = 1; #[repr(C)] diff --git a/crates/tests/core/tests/hstrings.rs b/crates/tests/core/tests/hstrings.rs index 7fab2806a4..0f4109bf01 100644 --- a/crates/tests/core/tests/hstrings.rs +++ b/crates/tests/core/tests/hstrings.rs @@ -53,6 +53,16 @@ fn from_empty_string() { assert!(format!("{}", h).is_empty()); } +#[test] +fn from_os_string_string() { + let wide_data = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; + use std::os::windows::prelude::OsStringExt; + let o = std::ffi::OsString::from_wide(wide_data); + let h = StringType::from(o); + let d = StringType::from_wide(wide_data); + assert_eq!(h, d); +} + #[test] fn hstring_to_string() { let h = StringType::from("test"); @@ -78,6 +88,16 @@ fn hstring_to_string_lossy() { assert_eq!(s, "𝄞mu�ic"); } +#[test] +fn hstring_to_os_string() { + // 𝄞muic + let wide_data = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; + let h = StringType::from_wide(wide_data); + let s = h.to_os_string(); + use std::os::windows::prelude::OsStringExt; + assert_eq!(s, std::ffi::OsString::from_wide(wide_data)); +} + #[test] fn hstring_equality_combinations() { let h = StringType::from("test"); @@ -104,3 +124,32 @@ fn hstring_equality_combinations() { assert_eq!(ss, h); assert_eq!(ss, &h); } + +#[test] +fn hstring_osstring_equality_combinations() { + let wide_data = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; + let h = StringType::from_wide(wide_data); + use std::os::windows::prelude::OsStringExt; + let s = std::ffi::OsString::from_wide(wide_data); + let ss = s.as_os_str(); + + assert_eq!(h, s); + assert_eq!(&h, s); + assert_eq!(h, &s); + assert_eq!(&h, &s); + + assert_eq!(s, h); + assert_eq!(s, &h); + assert_eq!(&s, h); + assert_eq!(&s, &h); + + assert_eq!(h, *ss); + assert_eq!(&h, *ss); + assert_eq!(h, ss); + assert_eq!(&h, ss); + + assert_eq!(*ss, h); + assert_eq!(*ss, &h); + assert_eq!(ss, h); + assert_eq!(ss, &h); +}