1#[cfg(feature = "std")]
2extern crate std;
3
4use core::fmt;
5
6cfg_if::cfg_if!(
7 if #[cfg(target_os = "uefi")] {
8 pub type RawOsError = usize;
17 type NonZeroRawOsError = core::num::NonZeroUsize;
18 const UEFI_ERROR_FLAG: RawOsError = 1 << (RawOsError::BITS - 1);
19 } else {
20 pub type RawOsError = i32;
26 type NonZeroRawOsError = core::num::NonZeroI32;
27 }
28);
29
30#[derive(#[automatically_derived]
impl ::core::marker::Copy for Error { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Error {
#[inline]
fn clone(&self) -> Error {
let _: ::core::clone::AssertParamIsClone<NonZeroRawOsError>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for Error {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<NonZeroRawOsError>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for Error {
#[inline]
fn eq(&self, other: &Error) -> bool { self.0 == other.0 }
}PartialEq)]
45pub struct Error(NonZeroRawOsError);
46
47impl Error {
48 pub const UNSUPPORTED: Error = Self::new_internal(0);
50 pub const ERRNO_NOT_POSITIVE: Error = Self::new_internal(1);
52 pub const UNEXPECTED: Error = Self::new_internal(2);
54
55 const INTERNAL_START: RawOsError = 1 << 16;
57 const CUSTOM_START: RawOsError = 1 << 17;
59
60 #[cfg(not(target_os = "uefi"))]
64 #[allow(dead_code)]
65 pub(super) fn from_errno(errno: i32) -> Self {
66 if errno > 0 {
67 let code = errno
68 .checked_neg()
69 .expect("Positive number can be always negated");
70 Error::from_neg_error_code(code)
71 } else {
72 Error::ERRNO_NOT_POSITIVE
73 }
74 }
75
76 #[cfg(not(target_os = "uefi"))]
80 #[allow(dead_code)]
81 pub(super) fn from_neg_error_code(code: RawOsError) -> Self {
82 if code < 0 {
83 let code = NonZeroRawOsError::new(code).expect("`code` is negative");
84 Self(code)
85 } else {
86 Error::UNEXPECTED
87 }
88 }
89
90 #[cfg(target_os = "uefi")]
92 #[allow(dead_code)]
93 pub(super) fn from_uefi_code(code: RawOsError) -> Self {
94 if code & UEFI_ERROR_FLAG != 0 {
95 let code = NonZeroRawOsError::new(code).expect("The highest bit of `code` is set to 1");
96 Self(code)
97 } else {
98 Self::UNEXPECTED
99 }
100 }
101
102 #[inline]
115 pub fn raw_os_error(self) -> Option<RawOsError> {
116 let code = self.0.get();
117
118 #[cfg(target_os = "uefi")]
123 {
124 if code & UEFI_ERROR_FLAG != 0 {
125 Some(code)
126 } else {
127 None
128 }
129 }
130
131 #[cfg(not(target_os = "uefi"))]
132 {
133 if code >= 0 {
143 None
144 } else if truecfg!(not(target_os = "solid_asp3")) {
145 code.checked_neg()
146 } else {
147 Some(code)
148 }
149 }
150 }
151
152 pub const fn new_custom(n: u16) -> Error {
154 let code = Error::CUSTOM_START + (n as RawOsError);
156 Error(unsafe { NonZeroRawOsError::new_unchecked(code) })
157 }
158
159 pub(crate) const fn new_internal(n: u16) -> Error {
161 let code = Error::INTERNAL_START + (n as RawOsError);
163 Error(unsafe { NonZeroRawOsError::new_unchecked(code) })
164 }
165
166 fn internal_desc(&self) -> Option<&'static str> {
167 let desc = match *self {
168 Error::UNSUPPORTED => "getrandom: this target is not supported",
169 Error::ERRNO_NOT_POSITIVE => "errno: did not return a positive value",
170 Error::UNEXPECTED => "unexpected situation",
171 #[cfg(any(
172 target_os = "ios",
173 target_os = "visionos",
174 target_os = "watchos",
175 target_os = "tvos",
176 ))]
177 Error::IOS_RANDOM_GEN => "SecRandomCopyBytes: iOS Security framework failure",
178 #[cfg(all(windows, target_vendor = "win7"))]
179 Error::WINDOWS_RTL_GEN_RANDOM => "RtlGenRandom: Windows system function failure",
180 #[cfg(all(
181 feature = "wasm_js",
182 target_arch = "wasm32",
183 any(target_os = "unknown", target_os = "none")
184 ))]
185 Error::WEB_CRYPTO => "Web Crypto API is unavailable",
186 #[cfg(target_os = "vxworks")]
187 Error::VXWORKS_RAND_SECURE => "randSecure: VxWorks RNG module is not initialized",
188
189 #[cfg(any(
190 getrandom_backend = "rdrand",
191 all(target_arch = "x86_64", target_env = "sgx")
192 ))]
193 Error::FAILED_RDRAND => "RDRAND: failed multiple times: CPU issue likely",
194 #[cfg(any(
195 getrandom_backend = "rdrand",
196 all(target_arch = "x86_64", target_env = "sgx")
197 ))]
198 Error::NO_RDRAND => "RDRAND: instruction not supported",
199
200 #[cfg(getrandom_backend = "rndr")]
201 Error::RNDR_FAILURE => "RNDR: Could not generate a random number",
202 #[cfg(getrandom_backend = "rndr")]
203 Error::RNDR_NOT_AVAILABLE => "RNDR: Register not supported",
204 _ => return None,
205 };
206 Some(desc)
207 }
208}
209
210impl core::error::Error for Error {}
211
212impl fmt::Debug for Error {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 let mut dbg = f.debug_struct("Error");
215 if let Some(errno) = self.raw_os_error() {
216 dbg.field("os_error", &errno);
217 #[cfg(feature = "std")]
218 dbg.field("description", &std::io::Error::from_raw_os_error(errno));
219 } else if let Some(desc) = self.internal_desc() {
220 dbg.field("internal_code", &self.0.get());
221 dbg.field("description", &desc);
222 } else {
223 dbg.field("unknown_code", &self.0.get());
224 }
225 dbg.finish()
226 }
227}
228
229impl fmt::Display for Error {
230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231 if let Some(errno) = self.raw_os_error() {
232 cfg_if! {
233 if #[cfg(feature = "std")] {
234 std::io::Error::from_raw_os_error(errno).fmt(f)
235 } else {
236 f.write_fmt(format_args!("OS Error: {0}", errno));write!(f, "OS Error: {errno}")
237 }
238 }
239 } else if let Some(desc) = self.internal_desc() {
240 f.write_str(desc)
241 } else {
242 f.write_fmt(format_args!("Unknown Error: {0}", self.0.get()))write!(f, "Unknown Error: {}", self.0.get())
243 }
244 }
245}