1use core::fmt;
4
5use apple_cf::CFError;
6
7use crate::ffi;
8
9pub type Result<T, E = SecurityError> = std::result::Result<T, E>;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct StatusError {
15 pub operation: &'static str,
17 pub status: ffi::OSStatus,
19 pub message: String,
21}
22
23impl fmt::Display for StatusError {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(
26 f,
27 "{} failed with OSStatus {}: {}",
28 self.operation, self.status, self.message
29 )
30 }
31}
32
33impl std::error::Error for StatusError {}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37#[non_exhaustive]
38pub enum SecurityError {
39 InvalidArgument(String),
41 ItemNotFound(String),
43 DuplicateItem(String),
45 InteractionNotAllowed(String),
47 TrustEvaluationFailed(String),
49 CoreFoundation(CFError),
51 UnexpectedType {
53 operation: &'static str,
55 expected: &'static str,
57 },
58 Status(StatusError),
60}
61
62impl SecurityError {
63 #[must_use]
65 pub const fn code(&self) -> Option<ffi::OSStatus> {
66 match self {
67 Self::ItemNotFound(_) => Some(ffi::status::ITEM_NOT_FOUND),
68 Self::DuplicateItem(_) => Some(ffi::status::DUPLICATE_ITEM),
69 Self::InteractionNotAllowed(_) => Some(ffi::status::INTERACTION_NOT_ALLOWED),
70 Self::Status(error) => Some(error.status),
71 _ => None,
72 }
73 }
74
75 pub(crate) const fn from_status(
76 operation: &'static str,
77 status: ffi::OSStatus,
78 message: String,
79 ) -> Self {
80 match status {
81 ffi::status::ITEM_NOT_FOUND => Self::ItemNotFound(message),
82 ffi::status::DUPLICATE_ITEM => Self::DuplicateItem(message),
83 ffi::status::INTERACTION_NOT_ALLOWED => Self::InteractionNotAllowed(message),
84 _ => Self::Status(StatusError {
85 operation,
86 status,
87 message,
88 }),
89 }
90 }
91}
92
93impl fmt::Display for SecurityError {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match self {
96 Self::InvalidArgument(message) => write!(f, "invalid argument: {message}"),
97 Self::ItemNotFound(message) => write!(f, "item not found: {message}"),
98 Self::DuplicateItem(message) => write!(f, "duplicate item: {message}"),
99 Self::InteractionNotAllowed(message) => write!(f, "interaction not allowed: {message}"),
100 Self::TrustEvaluationFailed(message) => write!(f, "trust evaluation failed: {message}"),
101 Self::CoreFoundation(error) => write!(f, "{error}"),
102 Self::UnexpectedType {
103 operation,
104 expected,
105 } => write!(
106 f,
107 "{operation} returned an unexpected Core Foundation type (expected {expected})"
108 ),
109 Self::Status(error) => write!(f, "{error}"),
110 }
111 }
112}
113
114impl std::error::Error for SecurityError {
115 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
116 match self {
117 Self::CoreFoundation(error) => Some(error),
118 Self::Status(error) => Some(error),
119 _ => None,
120 }
121 }
122}