1 | use super::*; |
2 | |
3 | /// An error code value returned by most COM functions. |
4 | #[repr (transparent)] |
5 | #[derive (Copy, Clone, Default, Eq, PartialEq)] |
6 | #[must_use ] |
7 | #[allow (non_camel_case_types)] |
8 | pub struct HRESULT(pub i32); |
9 | |
10 | impl HRESULT { |
11 | /// Returns [`true`] if `self` is a success code. |
12 | #[inline ] |
13 | pub const fn is_ok(self) -> bool { |
14 | self.0 >= 0 |
15 | } |
16 | |
17 | /// Returns [`true`] if `self` is a failure code. |
18 | #[inline ] |
19 | pub const fn is_err(self) -> bool { |
20 | !self.is_ok() |
21 | } |
22 | |
23 | /// Asserts that `self` is a success code. |
24 | /// |
25 | /// This will invoke the [`panic!`] macro if `self` is a failure code and display |
26 | /// the [`HRESULT`] value for diagnostics. |
27 | #[inline ] |
28 | #[track_caller ] |
29 | pub fn unwrap(self) { |
30 | assert!(self.is_ok(), "HRESULT 0x {:X}" , self.0); |
31 | } |
32 | |
33 | /// Converts the [`HRESULT`] to [`Result<()>`][Result<_>]. |
34 | #[inline ] |
35 | pub fn ok(self) -> Result<()> { |
36 | if self.is_ok() { |
37 | Ok(()) |
38 | } else { |
39 | Err(Error::from(self)) |
40 | } |
41 | } |
42 | |
43 | /// Returns the [`Option`] as a [`Result`] if the option is a [`Some`] value, returning |
44 | /// a suitable error if not. |
45 | pub fn and_some<T: Interface>(self, some: Option<T>) -> Result<T> { |
46 | if self.is_ok() { |
47 | if let Some(result) = some { |
48 | Ok(result) |
49 | } else { |
50 | Err(Error::OK) |
51 | } |
52 | } else { |
53 | Err(Error::from(self)) |
54 | } |
55 | } |
56 | |
57 | /// Calls `op` if `self` is a success code, otherwise returns [`HRESULT`] |
58 | /// converted to [`Result<T>`]. |
59 | #[inline ] |
60 | pub fn and_then<F, T>(self, op: F) -> Result<T> |
61 | where |
62 | F: FnOnce() -> T, |
63 | { |
64 | self.ok()?; |
65 | Ok(op()) |
66 | } |
67 | |
68 | /// If the [`Result`] is [`Ok`] converts the `T::Abi` into `T`. |
69 | /// |
70 | /// # Safety |
71 | /// |
72 | /// Safe to call if |
73 | /// * `abi` is initialized if `self` is `Ok` |
74 | /// * `abi` can be safely transmuted to `T` |
75 | pub unsafe fn from_abi<T: Type<T>>(self, abi: T::Abi) -> Result<T> { |
76 | if self.is_ok() { |
77 | T::from_abi(abi) |
78 | } else { |
79 | Err(Error::from(self)) |
80 | } |
81 | } |
82 | |
83 | /// The error message describing the error. |
84 | pub fn message(&self) -> HSTRING { |
85 | let mut message = HeapString(std::ptr::null_mut()); |
86 | |
87 | unsafe { |
88 | let size = crate::imp::FormatMessageW(crate::imp::FORMAT_MESSAGE_ALLOCATE_BUFFER | crate::imp::FORMAT_MESSAGE_FROM_SYSTEM | crate::imp::FORMAT_MESSAGE_IGNORE_INSERTS, std::ptr::null(), self.0 as u32, 0, &mut message.0 as *mut _ as *mut _, 0, std::ptr::null()); |
89 | |
90 | HSTRING::from_wide(crate::imp::wide_trim_end(std::slice::from_raw_parts(message.0 as *const u16, size as usize))).unwrap_or_default() |
91 | } |
92 | } |
93 | |
94 | /// Maps a Win32 error code to an HRESULT value. |
95 | pub const fn from_win32(error: u32) -> Self { |
96 | Self(if error as i32 <= 0 { error } else { (error & 0x0000_FFFF) | (7 << 16) | 0x8000_0000 } as i32) |
97 | } |
98 | } |
99 | |
100 | impl RuntimeType for HRESULT { |
101 | const SIGNATURE: crate::imp::ConstBuffer = crate::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.HResult;i32)" ); |
102 | } |
103 | |
104 | impl TypeKind for HRESULT { |
105 | type TypeKind = CopyType; |
106 | } |
107 | |
108 | impl<T> std::convert::From<Result<T>> for HRESULT { |
109 | fn from(result: Result<T>) -> Self { |
110 | if let Err(error: Error) = result { |
111 | return error.into(); |
112 | } |
113 | |
114 | HRESULT(0) |
115 | } |
116 | } |
117 | |
118 | impl std::fmt::Display for HRESULT { |
119 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
120 | f.write_fmt(format_args!(" {:#010X}" , self.0)) |
121 | } |
122 | } |
123 | |
124 | impl std::fmt::Debug for HRESULT { |
125 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
126 | f.write_fmt(format_args!("HRESULT( {})" , self)) |
127 | } |
128 | } |
129 | |
130 | struct HeapString(*mut u16); |
131 | |
132 | impl Drop for HeapString { |
133 | fn drop(&mut self) { |
134 | if !self.0.is_null() { |
135 | unsafe { |
136 | crate::imp::heap_free(self.0 as _); |
137 | } |
138 | } |
139 | } |
140 | } |
141 | |