use std::borrow::{Borrow, BorrowMut};
use std::fmt::{Debug, Formatter};
use std::ops::{Deref, DerefMut};
use windows::core::{HSTRING, PCWSTR};
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct U16Str([u16]);
impl U16Str {
unsafe fn from_slice_unsafe(slice: &[u16]) -> &Self {
let ptr: *const [u16] = slice;
&*(ptr as *const Self)
}
unsafe fn from_slice_mut_unsafe(slice: &mut [u16]) -> &mut Self {
let ptr: *mut [u16] = slice;
&mut *(ptr as *mut Self)
}
pub fn from_slice(slice: &[u16]) -> &Self {
assert!(slice.last().is_some_and(is_null), "Slice is not null terminated");
debug_assert_eq!(slice.iter().filter(|c| is_null(c)).count(), 1, "Found null character in the middle");
unsafe { Self::from_slice_unsafe(slice) }
}
pub fn from_slice_mut(slice: &mut [u16]) -> &mut Self {
assert!(slice.last().is_some_and(is_null), "Slice is not null terminated");
debug_assert_eq!(slice.iter().filter(|c| is_null(c)).count(), 1, "Found null character in the middle");
unsafe { Self::from_slice_mut_unsafe(slice) }
}
pub fn from_slice_list(slice: &[u16]) -> impl Iterator<Item = &U16Str> {
slice.split_inclusive(is_null).map(Self::from_slice)
}
pub fn from_slice_list_mut(slice: &mut [u16]) -> impl Iterator<Item = &mut U16Str> {
slice.split_inclusive_mut(is_null).map(Self::from_slice_mut)
}
pub fn as_ptr(&self) -> PCWSTR {
PCWSTR(self.0.as_ptr())
}
pub fn as_slice(&self) -> &[u16] {
&self.0[..self.0.len() - 1]
}
pub fn as_slice_mut(&mut self) -> &mut [u16] {
let end = self.0.len() - 1;
&mut self.0[..end]
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for U16Str {
fn to_string(&self) -> String {
String::from_utf16(self.as_slice()).expect("Invalid UTF-16")
}
}
impl Debug for U16Str {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "\"")?;
for c in char::decode_utf16(self.as_slice().iter().copied()) {
write!(f, "{}", c.unwrap_or(char::REPLACEMENT_CHARACTER))?;
}
write!(f, "\"")?;
Ok(())
}
}
impl ToOwned for U16Str {
type Owned = U16String;
fn to_owned(&self) -> Self::Owned {
U16String(self.0.to_vec())
}
}
impl From<&U16Str> for HSTRING {
fn from(value: &U16Str) -> Self {
HSTRING::from_wide(value.as_slice())
}
}
#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct U16String(Vec<u16>);
impl Debug for U16String {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.deref())
}
}
impl Deref for U16String {
type Target = U16Str;
fn deref(&self) -> &Self::Target {
unsafe { U16Str::from_slice_unsafe(self.0.as_slice()) }
}
}
impl DerefMut for U16String {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { U16Str::from_slice_mut_unsafe(self.0.as_mut_slice()) }
}
}
impl Borrow<U16Str> for U16String {
fn borrow(&self) -> &U16Str {
unsafe { U16Str::from_slice_unsafe(self.0.as_slice()) }
}
}
impl BorrowMut<U16Str> for U16String {
fn borrow_mut(&mut self) -> &mut U16Str {
unsafe { U16Str::from_slice_mut_unsafe(self.0.as_mut_slice()) }
}
}
pub struct U16StringList(Vec<u16>);
impl Debug for U16StringList {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl U16StringList {
pub unsafe fn from_vec_unchecked(vec: Vec<u16>) -> Self {
Self(vec)
}
pub fn iter(&self) -> impl Iterator<Item = &U16Str> {
let len = self.0.len() - 1;
U16Str::from_slice_list(&self.0.as_slice()[..len])
}
}
fn is_null(c: &u16) -> bool {
*c == 0
}