security_framework/
base.rs1use core_foundation::string::CFString;
4use core_foundation_sys::base::OSStatus;
5use std::error;
6use std::fmt;
7use std::num::NonZeroI32;
8use std::result;
9
10pub type Result<T, E = Error> = result::Result<T, E>;
12
13#[derive(Copy, Clone)]
15pub struct Error(NonZeroI32);
16
17impl fmt::Debug for Error {
18 #[cold]
19 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
20 let mut builder = fmt.debug_struct("Error");
21 builder.field("code", &self.0);
22 if let Some(message) = self.message() {
23 builder.field("message", &message);
24 }
25 builder.finish()
26 }
27}
28
29impl Error {
30 #[inline]
33 #[must_use]
34 pub fn from_code(code: OSStatus) -> Self {
35 Self(NonZeroI32::new(code).unwrap_or_else(|| NonZeroI32::new(1).unwrap()))
36 }
37
38 #[inline(always)]
40 #[must_use]
41 pub fn message(self) -> Option<String> {
42 self.inner_message()
43 }
44
45 #[cold]
46 fn inner_message(self) -> Option<String> {
47 use core_foundation::base::TCFType;
48 use security_framework_sys::base::SecCopyErrorMessageString;
49 use std::ptr;
50
51 unsafe {
52 let s = SecCopyErrorMessageString(self.code(), ptr::null_mut());
53 if s.is_null() {
54 None
55 } else {
56 Some(CFString::wrap_under_create_rule(s).to_string())
57 }
58 }
59 }
60
61 #[inline(always)]
63 #[must_use]
64 pub const fn code(self) -> OSStatus {
65 self.0.get() as _
66 }
67}
68
69impl From<OSStatus> for Error {
70 #[inline(always)]
71 #[must_use]
72 fn from(code: OSStatus) -> Self {
73 Self::from_code(code)
74 }
75}
76
77impl fmt::Display for Error {
78 #[cold]
79 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
80 if let Some(message) = self.message() {
81 write!(fmt, "{message}")
82 } else {
83 write!(fmt, "error code {}", self.code())
84 }
85 }
86}
87
88impl error::Error for Error {}