1use std::{fmt, sync::PoisonError};
28
29use num_enum::{FromPrimitive, IntoPrimitive};
30
31use crate::raw;
32
33pub type Result<T> = std::result::Result<T, Error>;
35
36#[derive(Clone)]
38pub struct Error {
39 kind: ErrorKind,
40 origin: Option<ErrorOrigin>,
41}
42
43#[derive(
45 Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromPrimitive, IntoPrimitive,
46)]
47#[repr(u32)]
48pub enum ErrorKind {
49 Generic = raw::TEEC_ERROR_GENERIC,
51 AccessDenied = raw::TEEC_ERROR_ACCESS_DENIED,
53 Cancel = raw::TEEC_ERROR_CANCEL,
55 AccessConflict = raw::TEEC_ERROR_ACCESS_CONFLICT,
57 ExcessData = raw::TEEC_ERROR_EXCESS_DATA,
59 BadFormat = raw::TEEC_ERROR_BAD_FORMAT,
61 BadParameters = raw::TEEC_ERROR_BAD_PARAMETERS,
63 BadState = raw::TEEC_ERROR_BAD_STATE,
65 ItemNotFound = raw::TEEC_ERROR_ITEM_NOT_FOUND,
67 NotImplemented = raw::TEEC_ERROR_NOT_IMPLEMENTED,
69 NotSupported = raw::TEEC_ERROR_NOT_SUPPORTED,
71 NoData = raw::TEEC_ERROR_NO_DATA,
73 OutOfMemory = raw::TEEC_ERROR_OUT_OF_MEMORY,
75 Busy = raw::TEEC_ERROR_BUSY,
77 Communication = raw::TEEC_ERROR_COMMUNICATION,
79 Security = raw::TEEC_ERROR_SECURITY,
81 ShortBuffer = raw::TEEC_ERROR_SHORT_BUFFER,
83 ExternalCancel = raw::TEEC_ERROR_EXTERNAL_CANCEL,
85 TargetDead = raw::TEEC_ERROR_TARGET_DEAD,
87 #[default]
89 Unknown,
90}
91
92impl ErrorKind {
93 pub(crate) fn as_str(&self) -> &'static str {
94 match self {
95 ErrorKind::Generic => "Non-specific cause.",
96 ErrorKind::AccessDenied => "Access privileges are not sufficient.",
97 ErrorKind::Cancel => "The operation was canceled.",
98 ErrorKind::AccessConflict => "Concurrent accesses caused conflict.",
99 ErrorKind::ExcessData => "Too much data for the requested operation was passed.",
100 ErrorKind::BadFormat => "Input data was of invalid format.",
101 ErrorKind::BadParameters => "Input parameters were invalid.",
102 ErrorKind::BadState => "Operation is not valid in the current state.",
103 ErrorKind::ItemNotFound => "The requested data item is not found.",
104 ErrorKind::NotImplemented => {
105 "The requested operation should exist but is not yet implemented."
106 }
107 ErrorKind::NotSupported => {
108 "The requested operation is valid but is not supported in this implementation."
109 }
110 ErrorKind::NoData => "Expected data was missing.",
111 ErrorKind::OutOfMemory => "System ran out of resources.",
112 ErrorKind::Busy => "The system is busy working on something else.",
113 ErrorKind::Communication => "Communication with a remote party failed.",
114 ErrorKind::Security => "A security fault was detected.",
115 ErrorKind::ShortBuffer => "The supplied buffer is too short for the generated output.",
116 ErrorKind::ExternalCancel => "Undocumented.",
117 ErrorKind::TargetDead => "Trusted Application has panicked during the operation.",
118 ErrorKind::Unknown => "Unknown error.",
119 }
120 }
121}
122
123impl Error {
124 pub fn new(kind: ErrorKind) -> Error {
125 Error { kind, origin: None }
126 }
127
128 pub fn from_raw_error(code: u32) -> Error {
130 Error {
131 kind: ErrorKind::from(code),
132 origin: None,
133 }
134 }
135
136 pub fn with_origin(mut self, origin: ErrorOrigin) -> Self {
138 self.origin = Some(origin);
139 self
140 }
141
142 pub fn kind(&self) -> ErrorKind {
144 self.kind
145 }
146
147 pub fn origin(&self) -> Option<ErrorOrigin> {
149 self.origin
150 }
151
152 pub fn raw_code(&self) -> u32 {
154 self.kind.into()
155 }
156
157 pub fn message(&self) -> &str {
159 self.kind().as_str()
160 }
161}
162
163impl<T> From<PoisonError<T>> for Error {
164 fn from(_: PoisonError<T>) -> Self {
165 Error::new(ErrorKind::Generic).with_origin(ErrorOrigin::API)
166 }
167}
168
169impl fmt::Debug for Error {
170 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
171 write!(
172 fmt,
173 "{} (错误代码 0x{:x}, 来源 0x{:x})",
174 self.message(),
175 self.raw_code(),
176 self.origin().map(|v| v.into()).unwrap_or(0_u32),
177 )
178 }
179}
180
181impl fmt::Display for Error {
182 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183 fmt::Debug::fmt(self, f)
184 }
185}
186
187impl std::error::Error for Error {
188 fn description(&self) -> &str {
189 self.message()
190 }
191}
192
193impl From<ErrorKind> for Error {
194 #[inline]
195 fn from(kind: ErrorKind) -> Error {
196 Error { kind, origin: None }
197 }
198}
199
200#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, IntoPrimitive)]
201#[repr(u32)]
202pub enum ErrorOrigin {
203 API = raw::TEEC_ORIGIN_API,
204 COMMS = raw::TEEC_ORIGIN_COMMS,
205 TEE = raw::TEEC_ORIGIN_TEE,
206 TA = raw::TEEC_ORIGIN_TRUSTED_APP,
207 #[default]
208 UNKNOWN,
209}
210
211#[cfg(test)]
212mod teec_error_tests {
213 use super::*;
214
215 macro_rules! test_error_kind_messages {
217 ($($variant:ident => $msg:expr),* $(,)?) => {
218 $(
219 assert_eq!(ErrorKind::$variant.as_str(), $msg);
220 )*
221 };
222 }
223
224 #[test]
225 fn test_error_types_and_methods() {
226 test_error_kind_messages! {
228 Generic => "Non-specific cause.",
229 AccessDenied => "Access privileges are not sufficient.",
230 Cancel => "The operation was canceled.",
231 AccessConflict => "Concurrent accesses caused conflict.",
232 ExcessData => "Too much data for the requested operation was passed.",
233 BadFormat => "Input data was of invalid format.",
234 BadParameters => "Input parameters were invalid.",
235 BadState => "Operation is not valid in the current state.",
236 ItemNotFound => "The requested data item is not found.",
237 NotImplemented => "The requested operation should exist but is not yet implemented.",
238 NotSupported => "The requested operation is valid but is not supported in this implementation.",
239 NoData => "Expected data was missing.",
240 OutOfMemory => "System ran out of resources.",
241 Busy => "The system is busy working on something else.",
242 Communication => "Communication with a remote party failed.",
243 Security => "A security fault was detected.",
244 ShortBuffer => "The supplied buffer is too short for the generated output.",
245 ExternalCancel => "Undocumented.",
246 TargetDead => "Trusted Application has panicked during the operation.",
247 Unknown => "Unknown error.",
248 }
249
250 let error = Error::new(ErrorKind::BadParameters);
252 assert_eq!(error.kind(), ErrorKind::BadParameters);
253 assert_eq!(error.origin(), None);
254
255 let raw_error = Error::from_raw_error(ErrorKind::Generic.into());
257 assert_eq!(raw_error.kind(), ErrorKind::Generic);
258
259 let error_with_origin = Error::new(ErrorKind::Generic).with_origin(ErrorOrigin::API);
261 assert_eq!(error_with_origin.origin(), Some(ErrorOrigin::API));
262
263 assert_eq!(error.raw_code(), u32::from(ErrorKind::BadParameters));
265
266 assert_eq!(error.message(), "Input parameters were invalid.");
268
269 let debug_str = format!("{:?}", error);
271 assert!(debug_str.contains("错误代码"));
272
273 let display_str = format!("{}", error);
275 assert!(display_str.contains("错误代码"));
276
277 let from_kind: Error = ErrorKind::OutOfMemory.into();
279 assert_eq!(from_kind.kind(), ErrorKind::OutOfMemory);
280
281 assert_eq!(u32::from(ErrorOrigin::API), raw::TEEC_ORIGIN_API);
283 assert_eq!(u32::from(ErrorOrigin::COMMS), raw::TEEC_ORIGIN_COMMS);
284 assert_eq!(u32::from(ErrorOrigin::TEE), raw::TEEC_ORIGIN_TEE);
285 assert_eq!(u32::from(ErrorOrigin::TA), raw::TEEC_ORIGIN_TRUSTED_APP);
286 }
287
288 #[test]
289 fn test_error_kind_all_variants_as_str() {
290 let error_kinds = vec![
292 ErrorKind::Generic,
293 ErrorKind::AccessDenied,
294 ErrorKind::Cancel,
295 ErrorKind::AccessConflict,
296 ErrorKind::ExcessData,
297 ErrorKind::BadFormat,
298 ErrorKind::BadParameters,
299 ErrorKind::BadState,
300 ErrorKind::ItemNotFound,
301 ErrorKind::NotImplemented,
302 ErrorKind::NotSupported,
303 ErrorKind::NoData,
304 ErrorKind::OutOfMemory,
305 ErrorKind::Busy,
306 ErrorKind::Communication,
307 ErrorKind::Security,
308 ErrorKind::ShortBuffer,
309 ErrorKind::ExternalCancel,
310 ErrorKind::TargetDead,
311 ErrorKind::Unknown,
312 ];
313
314 for kind in error_kinds {
315 let error = Error::new(kind);
316 let _ = error.kind();
318 }
319 }
320
321 #[test]
323 fn test_error_origin_to_u32() {
324 assert_eq!(u32::from(ErrorOrigin::API), raw::TEEC_ORIGIN_API);
325 assert_eq!(u32::from(ErrorOrigin::COMMS), raw::TEEC_ORIGIN_COMMS);
326 assert_eq!(u32::from(ErrorOrigin::TEE), raw::TEEC_ORIGIN_TEE);
327 assert_eq!(u32::from(ErrorOrigin::TA), raw::TEEC_ORIGIN_TRUSTED_APP);
328 }
329
330 #[test]
331 fn test_error_clone() {
332 let error = Error::new(ErrorKind::Communication).with_origin(ErrorOrigin::COMMS);
333 let cloned = error.clone();
334 assert_eq!(cloned.kind(), ErrorKind::Communication);
335 assert_eq!(cloned.origin(), Some(ErrorOrigin::COMMS));
336 }
337
338 #[test]
339 fn test_error_from_poison() {
340 let lock = std::sync::Mutex::new(42u32);
341 let lock_clone = std::sync::Arc::new(lock);
342 let lock_clone2 = lock_clone.clone();
343
344 let handle = std::thread::spawn(move || {
345 let _guard = lock_clone2.lock().unwrap();
346 panic!("intentional panic to poison mutex");
347 });
348 let _ = handle.join();
349
350 let error: Error = lock_clone.lock().unwrap_err().into();
351 assert_eq!(error.kind(), ErrorKind::Generic);
352 assert_eq!(error.origin(), Some(ErrorOrigin::API));
353 }
354
355 #[test]
356 fn test_error_display_with_origin() {
357 let error = Error::new(ErrorKind::Communication).with_origin(ErrorOrigin::COMMS);
358 let display = format!("{error}");
359 assert!(display.contains("Communication"));
360 assert!(display.contains("0x"));
362 }
363
364 #[test]
365 fn test_error_display_no_origin() {
366 let error = Error::new(ErrorKind::OutOfMemory);
367 let display = format!("{error}");
368 assert!(display.contains("resources"));
369 }
370
371 #[test]
372 fn test_error_debug_format() {
373 let error = Error::new(ErrorKind::Security).with_origin(ErrorOrigin::TEE);
374 let debug = format!("{error:?}");
375 assert!(debug.contains("security") || debug.contains("fault"));
377 assert!(debug.contains("0x"));
379 }
380
381 #[test]
382 fn test_error_origin_unknown() {
383 assert_eq!(u32::from(ErrorOrigin::UNKNOWN), 5);
384 assert_eq!(ErrorOrigin::from(5), ErrorOrigin::UNKNOWN);
385 }
386}