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