1use core::fmt;
4
5use apple_cf::CFError;
6
7pub type Result<T, E = SecurityError> = std::result::Result<T, E>;
9
10pub type OsStatus = i32;
12
13pub mod status {
15 use super::OsStatus;
16
17 pub const SUCCESS: OsStatus = 0;
18 pub const DUPLICATE_ITEM: OsStatus = -25_299;
19 pub const ITEM_NOT_FOUND: OsStatus = -25_300;
20 pub const INTERACTION_NOT_ALLOWED: OsStatus = -25_308;
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct StatusError {
26 pub operation: &'static str,
28 pub status: OsStatus,
30 pub message: String,
32}
33
34impl fmt::Display for StatusError {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 write!(
37 f,
38 "{} failed with OSStatus {}: {}",
39 self.operation, self.status, self.message
40 )
41 }
42}
43
44impl std::error::Error for StatusError {}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
48#[non_exhaustive]
49pub enum SecurityError {
50 InvalidArgument(String),
52 ItemNotFound(String),
54 DuplicateItem(String),
56 InteractionNotAllowed(String),
58 TrustEvaluationFailed(String),
60 UnexpectedType {
62 operation: &'static str,
64 expected: &'static str,
66 },
67 Serialization(String),
69 CoreFoundation(CFError),
71 Status(StatusError),
73}
74
75impl SecurityError {
76 #[must_use]
77 pub const fn code(&self) -> Option<OsStatus> {
78 match self {
79 Self::ItemNotFound(_) => Some(status::ITEM_NOT_FOUND),
80 Self::DuplicateItem(_) => Some(status::DUPLICATE_ITEM),
81 Self::InteractionNotAllowed(_) => Some(status::INTERACTION_NOT_ALLOWED),
82 Self::Status(error) => Some(error.status),
83 _ => None,
84 }
85 }
86
87 pub(crate) fn from_status(
88 operation: &'static str,
89 status: OsStatus,
90 message: String,
91 ) -> Self {
92 match status {
93 status::ITEM_NOT_FOUND => Self::ItemNotFound(message),
94 status::DUPLICATE_ITEM => Self::DuplicateItem(message),
95 status::INTERACTION_NOT_ALLOWED => Self::InteractionNotAllowed(message),
96 _ => Self::Status(StatusError {
97 operation,
98 status,
99 message,
100 }),
101 }
102 }
103}
104
105impl fmt::Display for SecurityError {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 match self {
108 Self::InvalidArgument(message) => write!(f, "invalid argument: {message}"),
109 Self::ItemNotFound(message) => write!(f, "item not found: {message}"),
110 Self::DuplicateItem(message) => write!(f, "duplicate item: {message}"),
111 Self::InteractionNotAllowed(message) => write!(f, "interaction not allowed: {message}"),
112 Self::TrustEvaluationFailed(message) => {
113 write!(f, "trust evaluation failed: {message}")
114 }
115 Self::UnexpectedType {
116 operation,
117 expected,
118 } => write!(
119 f,
120 "{operation} returned an unexpected value (expected {expected})"
121 ),
122 Self::Serialization(message) => write!(f, "serialization error: {message}"),
123 Self::CoreFoundation(error) => write!(f, "{error}"),
124 Self::Status(error) => write!(f, "{error}"),
125 }
126 }
127}
128
129impl std::error::Error for SecurityError {
130 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
131 match self {
132 Self::CoreFoundation(error) => Some(error),
133 Self::Status(error) => Some(error),
134 _ => None,
135 }
136 }
137}