winresult_types/
hresult.rs

1use crate::*;
2use core::convert::Infallible;
3use bytemuck::*;
4
5
6
7/// \[[docs.microsoft.com](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a)\]
8/// FACILITY_\* values corresponding to Microsoft (non-customer) `HRSEULT`s.
9///
10/// Note that NTSTATUS facilities, despite also being prefixed with FACILITY_\*, are incompatible (overlapping values interpreted differently!)
11#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct HResultFacilityMicrosoft(pub(crate) u16);
12
13impl HResultFacilityMicrosoft {
14    // Microsofts specs list facilities as only having 11 bits: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a
15    // However, DirectDraw and Direct3D9 uses 0x876, which sets a 12th bit.
16    // Additionally, Direct3D 10, Direct3D 11, etc. also get up into the 12 bits area.
17    // This goes into the reserved `X` bit.  Since Microsoft is using what Microsoft reserved, that's fine.
18    #[doc(hidden)] pub const fn from_constant(value: u16) -> Self { assert!(value <= 0xFFF, "HRESULT facilities are only 12 bits"); Self(value) }
19
20    pub const fn to_u16(self) -> u16 { self.0 }
21    pub const fn to_u32(self) -> u32 { self.0 as _ }
22}
23
24impl From<HResultFacilityMicrosoft> for u16 { fn from(f: HResultFacilityMicrosoft) -> Self { f.0 } }
25impl From<HResultFacilityMicrosoft> for u32 { fn from(f: HResultFacilityMicrosoft) -> Self { f.0.into() } }
26
27
28
29/// \[[docs.microsoft.com](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a)\]
30/// Success HRESULT
31#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Zeroable)] #[repr(transparent)] pub struct HResultSuccess(pub(crate) u32);
32// DO NOT IMPLEMENT:
33//  Pod (error bit patterns are forbidden)
34
35impl HResultSuccess {
36    #[doc(hidden)] pub const fn from_constant(value: u32) -> Self { assert!(value & 0x8000_0000 == 0, "HResultSuccess::from_constant: HRESULT is an error (high bit set)"); Self(value) }
37
38    //  const fn is_reserved(self) -> bool { self.0 & 0x40000000 != 0 }
39    pub const fn is_customer(self) -> bool { self.0 & 0x20000000 != 0 }
40    pub const fn is_ntstatus(self) -> bool { self.0 & 0x10000000 != 0 }
41
42    pub const fn facility   (self) -> u16  { (self.0 & 0x0FFF0000 >> 16) as _ }
43    pub const fn code       (self) -> u16  { self.0 as _ }
44    pub const fn to_u32     (self) -> u32  { self.0 }
45}
46
47impl From<HResultSuccess> for u32 { fn from(hr: HResultSuccess) -> Self { hr.0 } }
48impl From<HResultSuccess> for i32 { fn from(hr: HResultSuccess) -> Self { hr.0 as _ } } // for winapi interop
49impl From<Infallible> for HResultSuccess { fn from(i: Infallible) -> Self { match i {} } }
50
51#[allow(useless_deprecated)]
52#[deprecated = "allows the construction of 'successful' hresults from error values"]
53impl From<u32> for HResultSuccess { fn from(hr: u32) -> Self { Self(hr) } }
54
55
56
57/// \[[docs.microsoft.com](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a)\]
58/// Error HRESULT
59#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct HResultError(pub(crate) u32);
60// DO NOT IMPLEMENT:
61//  Pod         (success bit patterns are forbidden)
62//  Default     (0 is success)
63//  Zeroable    (0 is success)
64
65impl HResultError {
66    /// HRESULT_FROM_WIN32, but for errors specifically
67    pub const fn from_win32(value: ErrorCode) -> Self { Self(0x80070000 | (value.0 as u32)) }
68
69    #[doc(hidden)] pub const fn from_constant(value: u32) -> Self { assert!(value & 0x8000_0000 != 0, "HResultError::from_constant: HRESULT is a success (high bit not set)"); Self(value) }
70
71    //  const fn is_reserved(self) -> bool { self.0 & 0x40000000 != 0 }
72    pub const fn is_customer(self) -> bool { self.0 & 0x20000000 != 0 }
73    pub const fn is_ntstatus(self) -> bool { self.0 & 0x10000000 != 0 }
74
75    pub const fn facility   (self) -> u16  { (self.0 & 0x0FFF0000 >> 16) as _ }
76    pub const fn code       (self) -> u16  { self.0 as _ }
77    pub const fn to_u32     (self) -> u32  { self.0 }
78}
79
80impl From<HResultError> for u32 { fn from(hr: HResultError) -> Self { hr.0 } }
81impl From<HResultError> for i32 { fn from(hr: HResultError) -> Self { hr.0 as _ } } // for winapi interop
82impl From<(HResultFacilityMicrosoft, ErrorCode)> for HResultError { fn from((fac, code): (HResultFacilityMicrosoft, ErrorCode)) -> Self { Self(0x8000_0000 | (fac.to_u32()<<16) | code.to_u32()) } }
83impl From<Infallible> for HResultError { fn from(i: Infallible) -> Self { match i {} } }
84
85#[allow(useless_deprecated)]
86#[deprecated = "allows the construction of 'error' hresults from success values"]
87impl From<u32> for HResultError { fn from(hr: u32) -> Self { Self(hr) } }
88
89
90
91
92/// \[[docs.microsoft.com](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a)\]
93/// HRESULT
94#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Pod, Zeroable)] #[repr(transparent)] pub struct HResult(pub(crate) u32);
95
96impl HResult {
97    #[doc(hidden)] pub const fn from_constant(value: u32) -> Self { Self(value) }
98
99    pub const fn is_error   (self) -> bool { self.0 & 0x80000000 != 0 }
100    //  const fn is_reserved(self) -> bool { self.0 & 0x40000000 != 0 }
101    pub const fn is_customer(self) -> bool { self.0 & 0x20000000 != 0 }
102    pub const fn is_ntstatus(self) -> bool { self.0 & 0x10000000 != 0 }
103
104    pub const fn facility   (self) -> u16  { (self.0 & 0x0FFF0000 >> 16) as _ }
105    pub const fn code       (self) -> u16  { self.0 as _ }
106    pub const fn to_u32     (self) -> u32  { self.0 }
107
108    pub const fn succeeded(self) -> Result<HResultSuccess, HResultError> {
109        if self.is_error() {
110            Err(HResultError(self.0))
111        } else {
112            Ok(HResultSuccess(self.0))
113        }
114    }
115}
116
117impl From<HResult>          for u32     { fn from(hr: HResult       ) -> Self { hr.0 } }
118impl From<HResult>          for i32     { fn from(hr: HResult       ) -> Self { hr.0 as _ } } // for winapi interop
119impl From<u32>              for HResult { fn from(hr: u32           ) -> Self { Self(hr) } }
120impl From<i32>              for HResult { fn from(hr: i32           ) -> Self { Self(hr as _) } } // for winapi interop
121impl From<HResultSuccess>   for HResult { fn from(hr: HResultSuccess) -> Self { Self(hr.0) } }
122impl From<HResultError>     for HResult { fn from(hr: HResultError  ) -> Self { Self(hr.0) } }
123impl From<Infallible>       for HResult { fn from(i: Infallible     ) -> Self { match i {} } }
124impl From<(HResultFacilityMicrosoft, ErrorCode)> for HResult { fn from((fac, code): (HResultFacilityMicrosoft, ErrorCode)) -> Self { Self(0x8000_0000 | (fac.to_u32()<<16) | code.to_u32()) } }
125
126
127
128macro_rules! compare { ($($a:ident == $z:ident),* $(,)?) => {$(
129    impl PartialEq<$a> for $z { fn eq(&self, other: &$a) -> bool { HResult::from(*self).0 == HResult::from(*other).0 } }
130    impl PartialEq<$z> for $a { fn eq(&self, other: &$z) -> bool { HResult::from(*self).0 == HResult::from(*other).0 } }
131)*}}
132
133compare! {
134    HResult         == u32,
135    HResult         == i32, // winapi HRESULT
136    HResultSuccess  == HResult,
137    HResultSuccess  == u32,
138    HResultSuccess  == i32,
139    HResultError    == HResult,
140    HResultError    == u32,
141    HResultError    == i32,
142}
143
144impl<O, E: PartialEq<HResultError>> PartialEq<HResultError> for Result<O, E> {
145    fn eq(&self, other: &HResultError) -> bool {
146        match self.as_ref() {
147            Ok(_)   => false,
148            Err(e)  => *e == *other,
149        }
150    }
151}
152
153impl<O, E: PartialEq<HResultError>> PartialEq<Result<O, E>> for HResultError {
154    fn eq(&self, other: &Result<O, E>) -> bool {
155        match other.as_ref() {
156            Ok(_)   => false,
157            Err(e)  => *e == *self,
158        }
159    }
160}
161
162impl<O: PartialEq<HResultSuccess>, E> PartialEq<HResultSuccess> for Result<O, E> {
163    fn eq(&self, other: &HResultSuccess) -> bool {
164        match self.as_ref() {
165            Ok(o)   => *o == *other,
166            Err(_)  => false,
167        }
168    }
169}
170
171impl<O: PartialEq<HResultSuccess>, E> PartialEq<Result<O, E>> for HResultSuccess {
172    fn eq(&self, other: &Result<O, E>) -> bool {
173        match other.as_ref() {
174            Ok(o)   => *o == *self,
175            Err(_)  => false,
176        }
177    }
178}