use std::fmt;
use crate::Win32Error;
#[cfg(test)]
mod tests;
const SEVERITY_BIT: u32 = 0x8000_0000;
const CUSTOMER_BIT: u32 = 0x2000_0000;
pub(crate) const NTSTATUS_BIT: u32 = 0x1000_0000;
const FACILITY_SHIFT: u32 = 16;
const FACILITY_MASK: u32 = 0x1FFF;
const CODE_MASK: u32 = 0x0000_FFFF;
const SEVERITY_AND_FACILITY: u32 = 0xFFFF_0000;
const FACILITY_WIN32: u32 = 7;
const WIN32_WRAP: u32 = SEVERITY_BIT | (FACILITY_WIN32 << FACILITY_SHIFT);
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct HResult(i32);
impl HResult {
#[must_use]
pub const fn from_raw(raw: i32) -> Self {
Self(raw)
}
#[must_use]
pub const fn raw(self) -> i32 {
self.0
}
#[must_use]
pub const fn is_failure(self) -> bool {
self.0 < 0
}
#[must_use]
pub const fn is_success(self) -> bool {
!self.is_failure()
}
pub const fn into_result(self) -> Result<(), Self> {
if self.is_success() { Ok(()) } else { Err(self) }
}
#[must_use]
pub const fn code(self) -> u16 {
(self.0.cast_unsigned() & CODE_MASK) as u16
}
#[must_use]
pub const fn facility(self) -> u16 {
((self.0.cast_unsigned() >> FACILITY_SHIFT) & FACILITY_MASK) as u16
}
#[must_use]
pub const fn is_customer(self) -> bool {
self.0.cast_unsigned() & CUSTOMER_BIT != 0
}
#[must_use]
pub const fn is_ntstatus_mapped(self) -> bool {
self.0.cast_unsigned() & NTSTATUS_BIT != 0
}
#[must_use]
pub const fn from_win32(error: Win32Error) -> Self {
let code = error.code();
if code.cast_signed() <= 0 {
Self(code.cast_signed())
} else {
Self(((code & CODE_MASK) | WIN32_WRAP).cast_signed())
}
}
#[must_use]
pub const fn win32(self) -> Option<Win32Error> {
let bits = self.0.cast_unsigned();
if bits & SEVERITY_AND_FACILITY == WIN32_WRAP {
Some(Win32Error::from_code(bits & CODE_MASK))
} else {
None
}
}
}
impl fmt::Display for HResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:#010X}", self.0.cast_unsigned())
}
}
impl fmt::Debug for HResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "HResult({self})")
}
}