1 //! Support types for other modules. 2 3 use core_foundation::string::CFString; 4 use core_foundation_sys::base::OSStatus; 5 use std::error; 6 use std::fmt; 7 use std::result; 8 9 /// A `Result` type commonly returned by functions. 10 pub type Result<T> = result::Result<T, Error>; 11 12 /// A Security Framework error. 13 #[derive(Copy, Clone)] 14 pub struct Error(OSStatus); 15 16 impl fmt::Debug for Error { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result17 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 18 let mut builder = fmt.debug_struct("Error"); 19 builder.field("code", &self.0); 20 if let Some(message) = self.message() { 21 builder.field("message", &message); 22 } 23 builder.finish() 24 } 25 } 26 27 impl Error { 28 /// Creates a new `Error` from a status code. from_code(code: OSStatus) -> Self29 pub fn from_code(code: OSStatus) -> Self { 30 Self(code) 31 } 32 33 /// Returns a string describing the current error, if available. message(self) -> Option<String>34 pub fn message(self) -> Option<String> { 35 self.inner_message() 36 } 37 38 #[cfg(target_os = "macos")] inner_message(self) -> Option<String>39 fn inner_message(self) -> Option<String> { 40 use core_foundation::base::TCFType; 41 use security_framework_sys::base::SecCopyErrorMessageString; 42 use std::ptr; 43 44 unsafe { 45 let s = SecCopyErrorMessageString(self.0, ptr::null_mut()); 46 if s.is_null() { 47 None 48 } else { 49 Some(CFString::wrap_under_create_rule(s).to_string()) 50 } 51 } 52 } 53 54 #[cfg(not(target_os = "macos"))] inner_message(&self) -> Option<String>55 fn inner_message(&self) -> Option<String> { 56 None 57 } 58 59 /// Returns the code of the current error. code(self) -> OSStatus60 pub fn code(self) -> OSStatus { 61 self.0 62 } 63 } 64 65 impl From<OSStatus> for Error { from(code: OSStatus) -> Self66 fn from(code: OSStatus) -> Self { 67 Self::from_code(code) 68 } 69 } 70 71 impl fmt::Display for Error { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result72 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 73 if let Some(message) = self.message() { 74 write!(fmt, "{}", message) 75 } else { 76 write!(fmt, "error code {}", self.code()) 77 } 78 } 79 } 80 81 impl error::Error for Error { description(&self) -> &str82 fn description(&self) -> &str { 83 "Security Framework error" 84 } 85 } 86