use core::cmp::Ordering;
use core::marker::PhantomData;
use core::ops::Deref;
use core::{fmt, mem, slice};
use widestring::{U16CStr, U16Str};
use crate::error::Result;
use crate::helpers::RawNtString;
use crate::NtStringError;
use super::{impl_eq, impl_partial_cmp, NtUnicodeStr};
#[derive(Debug)]
#[repr(transparent)]
pub struct NtUnicodeStrMut<'a> {
raw: RawNtString<*mut u16>,
_lifetime: PhantomData<&'a ()>,
}
impl<'a> NtUnicodeStrMut<'a> {
pub fn as_mut_ptr(&mut self) -> *mut Self {
self as *mut Self
}
pub fn as_mut_slice(&mut self) -> &'a mut [u16] {
unsafe { slice::from_raw_parts_mut(self.raw.buffer, self.len_in_elements()) }
}
pub fn as_mut_u16str(&mut self) -> &'a U16Str {
U16Str::from_slice_mut(self.as_mut_slice())
}
pub fn as_unicode_str(&'a self) -> &'a NtUnicodeStr<'a> {
self.deref()
}
pub fn clear(&mut self) {
self.raw.length = 0;
}
pub const unsafe fn from_raw_parts(buffer: *mut u16, length: u16, maximum_length: u16) -> Self {
debug_assert!(length <= maximum_length);
Self {
raw: RawNtString {
length,
maximum_length,
buffer,
},
_lifetime: PhantomData,
}
}
pub fn pop(&mut self) -> Option<Result<char>> {
match self.chars().next_back()? {
Ok(c) => {
self.raw.length -= (c.len_utf16() * mem::size_of::<u16>()) as u16;
Some(Ok(c))
}
Err(e) => {
self.raw.length -= mem::size_of::<u16>() as u16;
Some(Err(e))
}
}
}
pub fn try_from_u16(buffer: &mut [u16]) -> Result<Self> {
let length = NtUnicodeStr::try_length_from_u16(buffer)?;
Ok(Self {
raw: RawNtString {
length,
maximum_length: length,
buffer: buffer.as_mut_ptr(),
},
_lifetime: PhantomData,
})
}
pub fn try_from_u16_until_nul(buffer: &mut [u16]) -> Result<Self> {
let (length, maximum_length) = NtUnicodeStr::try_length_from_u16_until_nul(buffer)?;
Ok(Self {
raw: RawNtString {
length,
maximum_length,
buffer: buffer.as_mut_ptr(),
},
_lifetime: PhantomData,
})
}
}
impl<'a> Deref for NtUnicodeStrMut<'a> {
type Target = NtUnicodeStr<'a>;
fn deref(&self) -> &Self::Target {
unsafe { mem::transmute(self) }
}
}
impl<'a> fmt::Display for NtUnicodeStrMut<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
}
}
impl<'a> Eq for NtUnicodeStrMut<'a> {}
impl<'a> Ord for NtUnicodeStrMut<'a> {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(self.deref(), other.deref())
}
}
impl<'a> TryFrom<&'a mut U16CStr> for NtUnicodeStrMut<'a> {
type Error = NtStringError;
fn try_from(value: &'a mut U16CStr) -> Result<Self> {
let (length, maximum_length) = NtUnicodeStr::try_length_from_u16_cstr(value)?;
Ok(Self {
raw: RawNtString {
length,
maximum_length,
buffer: value.as_mut_ptr(),
},
_lifetime: PhantomData,
})
}
}
impl<'a> TryFrom<&'a mut U16Str> for NtUnicodeStrMut<'a> {
type Error = NtStringError;
fn try_from(value: &'a mut U16Str) -> Result<Self> {
Self::try_from_u16(value.as_mut_slice())
}
}
impl_eq! { NtUnicodeStrMut<'a>, NtUnicodeStrMut<'b> }
impl_eq! { NtUnicodeStr<'a>, NtUnicodeStrMut<'b> }
impl_eq! { NtUnicodeStrMut<'a>, NtUnicodeStr<'b> }
impl_eq! { NtUnicodeStrMut<'a>, str }
impl_eq! { str, NtUnicodeStrMut<'a> }
impl_eq! { NtUnicodeStrMut<'a>, &str }
impl_eq! { &str, NtUnicodeStrMut<'a> }
impl_partial_cmp! { NtUnicodeStrMut<'a>, NtUnicodeStrMut<'b> }
impl_partial_cmp! { NtUnicodeStr<'a>, NtUnicodeStrMut<'b> }
impl_partial_cmp! { NtUnicodeStrMut<'a>, NtUnicodeStr<'b> }
impl_partial_cmp! { NtUnicodeStrMut<'a>, str }
impl_partial_cmp! { str, NtUnicodeStrMut<'a> }
impl_partial_cmp! { NtUnicodeStrMut<'a>, &str }
impl_partial_cmp! { &str, NtUnicodeStrMut<'a> }