1use std::{fmt, sync::PoisonError};
21
22use num_enum::{FromPrimitive, IntoPrimitive};
23
24use crate::raw;
25
26pub type Result<T> = std::result::Result<T, Error>;
28
29#[derive(Clone)]
31pub struct Error {
32 kind: ErrorKind,
33 origin: Option<ErrorOrigin>,
34}
35
36#[derive(
38 Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromPrimitive, IntoPrimitive,
39)]
40#[repr(u32)]
41pub enum ErrorKind {
42 Generic = raw::TEEC_ERROR_GENERIC,
44 AccessDenied = raw::TEEC_ERROR_ACCESS_DENIED,
46 Cancel = raw::TEEC_ERROR_CANCEL,
48 AccessConflict = raw::TEEC_ERROR_ACCESS_CONFLICT,
50 ExcessData = raw::TEEC_ERROR_EXCESS_DATA,
52 BadFormat = raw::TEEC_ERROR_BAD_FORMAT,
54 BadParameters = raw::TEEC_ERROR_BAD_PARAMETERS,
56 BadState = raw::TEEC_ERROR_BAD_STATE,
58 ItemNotFound = raw::TEEC_ERROR_ITEM_NOT_FOUND,
60 NotImplemented = raw::TEEC_ERROR_NOT_IMPLEMENTED,
62 NotSupported = raw::TEEC_ERROR_NOT_SUPPORTED,
64 NoData = raw::TEEC_ERROR_NO_DATA,
66 OutOfMemory = raw::TEEC_ERROR_OUT_OF_MEMORY,
68 Busy = raw::TEEC_ERROR_BUSY,
70 Communication = raw::TEEC_ERROR_COMMUNICATION,
72 Security = raw::TEEC_ERROR_SECURITY,
74 ShortBuffer = raw::TEEC_ERROR_SHORT_BUFFER,
76 ExternalCancel = raw::TEEC_ERROR_EXTERNAL_CANCEL,
78 TargetDead = raw::TEEC_ERROR_TARGET_DEAD,
80 #[default]
82 Unknown,
83}
84
85impl ErrorKind {
86 pub(crate) fn as_str(&self) -> &'static str {
87 match self {
88 ErrorKind::Generic => "Non-specific cause.",
89 ErrorKind::AccessDenied => "Access privileges are not sufficient.",
90 ErrorKind::Cancel => "The operation was canceled.",
91 ErrorKind::AccessConflict => "Concurrent accesses caused conflict.",
92 ErrorKind::ExcessData => "Too much data for the requested operation was passed.",
93 ErrorKind::BadFormat => "Input data was of invalid format.",
94 ErrorKind::BadParameters => "Input parameters were invalid.",
95 ErrorKind::BadState => "Operation is not valid in the current state.",
96 ErrorKind::ItemNotFound => "The requested data item is not found.",
97 ErrorKind::NotImplemented => {
98 "The requested operation should exist but is not yet implemented."
99 }
100 ErrorKind::NotSupported => {
101 "The requested operation is valid but is not supported in this implementation."
102 }
103 ErrorKind::NoData => "Expected data was missing.",
104 ErrorKind::OutOfMemory => "System ran out of resources.",
105 ErrorKind::Busy => "The system is busy working on something else.",
106 ErrorKind::Communication => "Communication with a remote party failed.",
107 ErrorKind::Security => "A security fault was detected.",
108 ErrorKind::ShortBuffer => "The supplied buffer is too short for the generated output.",
109 ErrorKind::ExternalCancel => "Undocumented.",
110 ErrorKind::TargetDead => "Trusted Application has panicked during the operation.",
111 ErrorKind::Unknown => "Unknown error.",
112 }
113 }
114}
115
116impl Error {
117 pub fn new(kind: ErrorKind) -> Error {
118 Error { kind, origin: None }
119 }
120
121 pub fn from_raw_error(code: u32) -> Error {
123 Error {
124 kind: ErrorKind::from(code),
125 origin: None,
126 }
127 }
128
129 pub fn with_origin(mut self, origin: ErrorOrigin) -> Self {
131 self.origin = Some(origin);
132 self
133 }
134
135 pub fn kind(&self) -> ErrorKind {
137 self.kind
138 }
139
140 pub fn origin(&self) -> Option<ErrorOrigin> {
142 self.origin
143 }
144
145 pub fn raw_code(&self) -> u32 {
147 self.kind.into()
148 }
149
150 pub fn message(&self) -> &str {
152 self.kind().as_str()
153 }
154}
155
156impl<T> From<PoisonError<T>> for Error {
157 fn from(_: PoisonError<T>) -> Self {
158 Error::new(ErrorKind::Generic).with_origin(ErrorOrigin::API)
159 }
160}
161
162impl fmt::Debug for Error {
163 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
164 write!(
165 fmt,
166 "{} (错误代码 0x{:x}, 来源 0x{:x})",
167 self.message(),
168 self.raw_code(),
169 self.origin().map(|v| v.into()).unwrap_or(0_u32),
170 )
171 }
172}
173
174impl fmt::Display for Error {
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 fmt::Debug::fmt(self, f)
177 }
178}
179
180impl std::error::Error for Error {
181 fn description(&self) -> &str {
182 self.message()
183 }
184}
185
186impl From<ErrorKind> for Error {
187 #[inline]
188 fn from(kind: ErrorKind) -> Error {
189 Error { kind, origin: None }
190 }
191}
192
193#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, IntoPrimitive)]
194#[repr(u32)]
195pub enum ErrorOrigin {
196 API = raw::TEEC_ORIGIN_API,
197 COMMS = raw::TEEC_ORIGIN_COMMS,
198 TEE = raw::TEEC_ORIGIN_TEE,
199 TA = raw::TEEC_ORIGIN_TRUSTED_APP,
200 #[default]
201 UNKNOWN,
202}
203
204#[cfg(test)]
205mod teec_error_tests {
206 use super::*;
207
208 macro_rules! test_error_kind_messages {
210 ($($variant:ident => $msg:expr),* $(,)?) => {
211 $(
212 assert_eq!(ErrorKind::$variant.as_str(), $msg);
213 )*
214 };
215 }
216
217 #[test]
218 fn test_error_types_and_methods() {
219 test_error_kind_messages! {
221 Generic => "Non-specific cause.",
222 AccessDenied => "Access privileges are not sufficient.",
223 Cancel => "The operation was canceled.",
224 AccessConflict => "Concurrent accesses caused conflict.",
225 ExcessData => "Too much data for the requested operation was passed.",
226 BadFormat => "Input data was of invalid format.",
227 BadParameters => "Input parameters were invalid.",
228 BadState => "Operation is not valid in the current state.",
229 ItemNotFound => "The requested data item is not found.",
230 NotImplemented => "The requested operation should exist but is not yet implemented.",
231 NotSupported => "The requested operation is valid but is not supported in this implementation.",
232 NoData => "Expected data was missing.",
233 OutOfMemory => "System ran out of resources.",
234 Busy => "The system is busy working on something else.",
235 Communication => "Communication with a remote party failed.",
236 Security => "A security fault was detected.",
237 ShortBuffer => "The supplied buffer is too short for the generated output.",
238 ExternalCancel => "Undocumented.",
239 TargetDead => "Trusted Application has panicked during the operation.",
240 Unknown => "Unknown error.",
241 }
242
243 let error = Error::new(ErrorKind::BadParameters);
245 assert_eq!(error.kind(), ErrorKind::BadParameters);
246 assert_eq!(error.origin(), None);
247
248 let raw_error = Error::from_raw_error(ErrorKind::Generic.into());
250 assert_eq!(raw_error.kind(), ErrorKind::Generic);
251
252 let error_with_origin = Error::new(ErrorKind::Generic).with_origin(ErrorOrigin::API);
254 assert_eq!(error_with_origin.origin(), Some(ErrorOrigin::API));
255
256 assert_eq!(error.raw_code(), u32::from(ErrorKind::BadParameters));
258
259 assert_eq!(error.message(), "Input parameters were invalid.");
261
262 let debug_str = format!("{:?}", error);
264 assert!(debug_str.contains("错误代码"));
265
266 let display_str = format!("{}", error);
268 assert!(display_str.contains("错误代码"));
269
270 let from_kind: Error = ErrorKind::OutOfMemory.into();
272 assert_eq!(from_kind.kind(), ErrorKind::OutOfMemory);
273
274 assert_eq!(u32::from(ErrorOrigin::API), raw::TEEC_ORIGIN_API);
276 assert_eq!(u32::from(ErrorOrigin::COMMS), raw::TEEC_ORIGIN_COMMS);
277 assert_eq!(u32::from(ErrorOrigin::TEE), raw::TEEC_ORIGIN_TEE);
278 assert_eq!(u32::from(ErrorOrigin::TA), raw::TEEC_ORIGIN_TRUSTED_APP);
279 }
280
281 #[test]
282 fn test_error_kind_all_variants_as_str() {
283 let error_kinds = vec![
285 ErrorKind::Generic,
286 ErrorKind::AccessDenied,
287 ErrorKind::Cancel,
288 ErrorKind::AccessConflict,
289 ErrorKind::ExcessData,
290 ErrorKind::BadFormat,
291 ErrorKind::BadParameters,
292 ErrorKind::BadState,
293 ErrorKind::ItemNotFound,
294 ErrorKind::NotImplemented,
295 ErrorKind::NotSupported,
296 ErrorKind::NoData,
297 ErrorKind::OutOfMemory,
298 ErrorKind::Busy,
299 ErrorKind::Communication,
300 ErrorKind::Security,
301 ErrorKind::ShortBuffer,
302 ErrorKind::ExternalCancel,
303 ErrorKind::TargetDead,
304 ErrorKind::Unknown,
305 ];
306
307 for kind in error_kinds {
308 let error = Error::new(kind);
309 let _ = error.kind();
311 }
312 }
313
314 #[test]
316 fn test_error_origin_to_u32() {
317 assert_eq!(u32::from(ErrorOrigin::API), raw::TEEC_ORIGIN_API);
318 assert_eq!(u32::from(ErrorOrigin::COMMS), raw::TEEC_ORIGIN_COMMS);
319 assert_eq!(u32::from(ErrorOrigin::TEE), raw::TEEC_ORIGIN_TEE);
320 assert_eq!(u32::from(ErrorOrigin::TA), raw::TEEC_ORIGIN_TRUSTED_APP);
321 }
322}