graphannis_capi/
cerror.rs1use super::cast_const;
2use super::data::{vec_get, vec_size};
3use graphannis::errors;
4use libc::{c_char, size_t};
5use std::error::Error as StdError;
6use std::ffi::CString;
7
8pub struct Error {
10 pub msg: CString,
12 pub kind: CString,
14}
15
16pub type ErrorList = Vec<Error>;
18
19struct CauseIterator<'a> {
20 current: Option<&'a dyn StdError>,
21}
22
23impl std::iter::Iterator for CauseIterator<'_> {
24 type Item = Error;
25
26 fn next(&mut self) -> std::option::Option<Error> {
27 let std_error = self.current?;
28 let result = Error {
29 msg: CString::new(std_error.to_string()).unwrap_or_default(),
30 kind: CString::new("Cause").unwrap_or_default(),
31 };
32 self.current = std_error.source();
33 Some(result)
34 }
35}
36
37#[allow(clippy::borrowed_box)]
38fn error_kind(e: &Box<dyn StdError>) -> &'static str {
39 if let Some(annis_err) = e.downcast_ref::<errors::GraphAnnisError>() {
40 annis_err.into()
41 } else {
42 if e.is::<std::io::Error>() {
44 "IO"
45 } else if e.is::<log::SetLoggerError>() {
46 "SetLoggerError"
47 } else {
48 "Unknown"
49 }
50 }
51}
52
53pub fn create_error_list(e: Box<dyn StdError>) -> ErrorList {
54 let mut result = vec![Error {
55 msg: CString::new(e.to_string()).unwrap_or_default(),
56 kind: CString::new(error_kind(&e)).unwrap_or_default(),
57 }];
58 let cause_it = CauseIterator {
59 current: e.source(),
60 };
61 for e in cause_it {
62 result.push(e)
63 }
64 result
65}
66
67impl From<log::SetLoggerError> for Error {
68 fn from(e: log::SetLoggerError) -> Error {
69 if let Ok(error_msg) = CString::new(e.to_string()) {
70 Error {
71 msg: error_msg,
72 kind: CString::new("SetLoggerError").unwrap(),
73 }
74 } else {
75 Error {
77 msg: CString::new(String::from("Some error occurred")).unwrap(),
78 kind: CString::new("SetLoggerError").unwrap(),
79 }
80 }
81 }
82}
83
84impl From<std::io::Error> for Error {
85 fn from(e: std::io::Error) -> Error {
86 if let Ok(error_msg) = CString::new(e.to_string()) {
87 Error {
88 msg: error_msg,
89 kind: CString::new("std::io::Error").unwrap(),
90 }
91 } else {
92 Error {
94 msg: CString::new(String::from("Some error occurred")).unwrap(),
95 kind: CString::new("std::io::Error").unwrap(),
96 }
97 }
98 }
99}
100pub fn new(err: Box<dyn StdError>) -> *mut ErrorList {
102 Box::into_raw(Box::new(create_error_list(err)))
103}
104
105#[unsafe(no_mangle)]
107pub extern "C" fn annis_error_size(ptr: *const ErrorList) -> size_t {
108 vec_size(ptr)
109}
110
111#[unsafe(no_mangle)]
113pub extern "C" fn annis_error_get_msg(ptr: *const ErrorList, i: size_t) -> *const c_char {
114 let item = vec_get(ptr, i);
115 if item.is_null() {
116 return std::ptr::null();
117 }
118 let err: &Error = cast_const(item);
119 err.msg.as_ptr()
120}
121
122#[unsafe(no_mangle)]
124pub extern "C" fn annis_error_get_kind(ptr: *const ErrorList, i: size_t) -> *const c_char {
125 let item = vec_get(ptr, i);
126 if item.is_null() {
127 return std::ptr::null();
128 }
129 let err: &Error = cast_const(item);
130 err.kind.as_ptr()
131}