tesseract_swift_transport/
error.rs

1use std::mem::ManuallyDrop;
2use thiserror;
3use tesseract_one::{Error as TError, ErrorKind};
4use tesseract_swift_utils::{error::{CError, CErrorCode, ErrorCode, SwiftError},
5                            traits::TryAsRef, string::CString};
6
7/// cbindgen:add-sentinel
8#[repr(u32)]
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
10pub enum CTesseractErrorCode {
11    Logger = CErrorCode::Sentinel,
12    Cancelled,
13    Serialization,
14    Weird
15}
16
17impl ErrorCode for CTesseractErrorCode {
18    const FIRST: u32 = CTesseractErrorCode::Logger as u32;
19    #[allow(non_upper_case_globals)]
20    const Sentinel: u32 = CTesseractErrorCode::Weird as u32 + 1;
21}
22
23#[repr(C)]
24#[derive(Debug, thiserror::Error)]
25pub enum TesseractSwiftError {
26    #[error("TesseractSwiftError::Interop: {0}")]
27    Interop(CError),
28    #[error("TesseractSwiftError::Swift: {0}")]
29    Swift(SwiftError),
30    #[error("TesseractSwiftError::Logger: {0}")]
31    Logger(String),
32    #[error("TesseractSwiftError::Tesseract: {0}")]
33    Tesseract(TError),
34    #[error("TesseractSwiftError[{0}]: {1}")]
35    Custom(u32, String)
36}
37
38impl TesseractSwiftError {
39    pub fn is_cancelled(&self) -> bool {
40        match self {
41            Self::Tesseract(terror) => match terror.kind {
42                ErrorKind::Cancelled => true,
43                _ => false
44            },
45            _ => false
46        }
47    }
48}
49
50impl From<CError> for TesseractSwiftError {
51    fn from(value: CError) -> Self {
52        match CErrorCode::from_u32(value.code) {
53            Some(code) => match code {
54                CErrorCode::Swift => {
55                    match SwiftError::try_from(&value) {
56                        Err(err) => err.into(),
57                        Ok(err) => Self::Swift(err)
58                    }
59                },
60                _ => Self::Interop(value)
61            },
62            None => match CTesseractErrorCode::from_u32(value.code) {
63                Some(code) => match code {
64                    CTesseractErrorCode::Logger => Self::Logger(value.reason.try_into().unwrap()),
65                    CTesseractErrorCode::Cancelled => 
66                        Self::Tesseract(TError::described(ErrorKind::Cancelled, value.reason.try_as_ref().unwrap())),
67                    CTesseractErrorCode::Serialization =>
68                        Self::Tesseract(TError::described(ErrorKind::Serialization, value.reason.try_as_ref().unwrap())),
69                    CTesseractErrorCode::Weird =>
70                    Self::Tesseract(TError::described(ErrorKind::Weird, value.reason.try_as_ref().unwrap())),
71                },
72                None => Self::Custom(value.code - CTesseractErrorCode::Sentinel, value.reason.try_into().unwrap())
73            }
74        }
75    }
76}
77
78impl From<TesseractSwiftError> for CError {
79    fn from(value: TesseractSwiftError) -> Self {
80        match value {
81            TesseractSwiftError::Interop(error) => error,
82            TesseractSwiftError::Swift(error) => match error.try_into() {
83                Err(err) => err,
84                Ok(err) => err
85            },
86            TesseractSwiftError::Logger(reason) => 
87                CError { code: CTesseractErrorCode::Logger as u32, reason: reason.into() },
88            TesseractSwiftError::Tesseract(error) => {
89                let reason = error.description.unwrap_or_default();
90                match error.kind {
91                    ErrorKind::Cancelled => 
92                        CError { code: CTesseractErrorCode::Cancelled as u32, reason: reason.into() },
93                    ErrorKind::Serialization => 
94                        CError { code: CTesseractErrorCode::Serialization as u32, reason: reason.into() },
95                    ErrorKind::Weird => 
96                        CError { code: CTesseractErrorCode::Weird as u32, reason: reason.into() }
97                }
98            },
99            TesseractSwiftError::Custom(code, reason) =>
100                CError { code: code + CTesseractErrorCode::Sentinel, reason: reason.into() }
101        }
102    }
103}
104
105impl From<TError> for TesseractSwiftError {
106    fn from(value: TError) -> Self {
107        match value.kind {
108            ErrorKind::Weird => {
109                let reason = value.description.unwrap_or_else(|| String::new());
110                let parts: Vec<&str> = reason.split(" :: ").collect();
111                if parts.len() != 2 {
112                    return Self::Tesseract(TError::described(ErrorKind::Weird, &reason.clone()));
113                }
114                match parts[0].parse::<u32>() {
115                    Err(_) => Self::Tesseract(TError::described(ErrorKind::Weird, &reason.clone())),
116                    Ok(code) => CError::new(code, parts[1].to_owned()).into()
117                }
118            },
119            _ => Self::Tesseract(value)
120        }
121    }
122}
123
124impl From<TesseractSwiftError> for TError {
125    fn from(value: TesseractSwiftError) -> Self {
126        match value {
127            TesseractSwiftError::Tesseract(err) => err,
128            err => {
129                let cerr: CError = err.into();
130                TError::described(ErrorKind::Weird, &format!("{} :: {}", cerr.code, cerr.reason))
131            }
132        }
133    }
134}
135
136impl From<log::SetLoggerError> for TesseractSwiftError {
137    fn from(value: log::SetLoggerError) -> Self {
138        Self::Logger(value.to_string())
139    }
140}
141
142#[no_mangle]
143pub unsafe extern "C" fn tesseract_error_get_description(err: &CError) -> ManuallyDrop<CString> {
144    let tesseract: TesseractSwiftError = err.clone().into();
145    ManuallyDrop::new(tesseract.to_string().into())
146}