1use std::cell::Cell;
2use std::ffi::c_char;
3
4use blazesym::ErrorKind;
5
6
7#[repr(transparent)]
11#[derive(Copy, Clone, Debug, Eq, PartialEq)]
12pub struct blaze_err(i16);
13
14impl blaze_err {
15 pub const OK: blaze_err = blaze_err(0);
17 pub const NOT_FOUND: blaze_err = blaze_err(-2);
19 pub const PERMISSION_DENIED: blaze_err = blaze_err(-1);
21 pub const ALREADY_EXISTS: blaze_err = blaze_err(-17);
23 pub const WOULD_BLOCK: blaze_err = blaze_err(-11);
26 pub const INVALID_DATA: blaze_err = blaze_err(-22);
28 pub const TIMED_OUT: blaze_err = blaze_err(-110);
30 pub const UNSUPPORTED: blaze_err = blaze_err(-95);
32 pub const OUT_OF_MEMORY: blaze_err = blaze_err(-12);
35 pub const INVALID_INPUT: blaze_err = blaze_err(-256);
37 pub const WRITE_ZERO: blaze_err = blaze_err(-257);
40 pub const UNEXPECTED_EOF: blaze_err = blaze_err(-258);
43 pub const INVALID_DWARF: blaze_err = blaze_err(-259);
45 pub const OTHER: blaze_err = blaze_err(-260);
48}
49
50impl From<ErrorKind> for blaze_err {
51 fn from(other: ErrorKind) -> Self {
52 match other {
53 ErrorKind::NotFound => blaze_err::NOT_FOUND,
54 ErrorKind::PermissionDenied => blaze_err::PERMISSION_DENIED,
55 ErrorKind::AlreadyExists => blaze_err::ALREADY_EXISTS,
56 ErrorKind::WouldBlock => blaze_err::WOULD_BLOCK,
57 ErrorKind::InvalidInput => blaze_err::INVALID_INPUT,
58 ErrorKind::InvalidData => blaze_err::INVALID_DATA,
59 ErrorKind::InvalidDwarf => blaze_err::INVALID_DWARF,
60 ErrorKind::TimedOut => blaze_err::TIMED_OUT,
61 ErrorKind::WriteZero => blaze_err::WRITE_ZERO,
62 ErrorKind::Unsupported => blaze_err::UNSUPPORTED,
63 ErrorKind::UnexpectedEof => blaze_err::UNEXPECTED_EOF,
64 ErrorKind::OutOfMemory => blaze_err::OUT_OF_MEMORY,
65 ErrorKind::Other => blaze_err::OTHER,
66 _ => unreachable!(),
67 }
68 }
69}
70
71
72thread_local! {
73 static LAST_ERR: Cell<blaze_err> = const { Cell::new(blaze_err::OK) };
75}
76
77#[no_mangle]
79pub extern "C" fn blaze_err_last() -> blaze_err {
80 LAST_ERR.with(Cell::get)
81}
82
83pub(crate) fn set_last_err(err: blaze_err) {
85 LAST_ERR.with(|cell| cell.set(err))
86}
87
88
89#[no_mangle]
91pub extern "C" fn blaze_err_str(err: blaze_err) -> *const c_char {
92 match err {
93 blaze_err::OK => b"success\0".as_ptr().cast(),
94 blaze_err::NOT_FOUND => ErrorKind::NotFound.as_bytes().as_ptr().cast(),
95 blaze_err::PERMISSION_DENIED => ErrorKind::PermissionDenied.as_bytes().as_ptr().cast(),
96 blaze_err::ALREADY_EXISTS => ErrorKind::AlreadyExists.as_bytes().as_ptr().cast(),
97 blaze_err::WOULD_BLOCK => ErrorKind::WouldBlock.as_bytes().as_ptr().cast(),
98 blaze_err::INVALID_INPUT => ErrorKind::InvalidInput.as_bytes().as_ptr().cast(),
99 blaze_err::INVALID_DATA => ErrorKind::InvalidData.as_bytes().as_ptr().cast(),
100 blaze_err::INVALID_DWARF => ErrorKind::InvalidDwarf.as_bytes().as_ptr().cast(),
101 blaze_err::TIMED_OUT => ErrorKind::TimedOut.as_bytes().as_ptr().cast(),
102 blaze_err::WRITE_ZERO => ErrorKind::WriteZero.as_bytes().as_ptr().cast(),
103 blaze_err::UNSUPPORTED => ErrorKind::Unsupported.as_bytes().as_ptr().cast(),
104 blaze_err::UNEXPECTED_EOF => ErrorKind::UnexpectedEof.as_bytes().as_ptr().cast(),
105 blaze_err::OUT_OF_MEMORY => ErrorKind::OutOfMemory.as_bytes().as_ptr().cast(),
106 _ => ErrorKind::Other.as_bytes().as_ptr().cast(),
107 }
108}
109
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 use std::ffi::CStr;
116
117
118 #[test]
120 fn error_conversion() {
121 let data = [
122 (ErrorKind::NotFound, blaze_err::NOT_FOUND),
123 (ErrorKind::PermissionDenied, blaze_err::PERMISSION_DENIED),
124 (ErrorKind::AlreadyExists, blaze_err::ALREADY_EXISTS),
125 (ErrorKind::WouldBlock, blaze_err::WOULD_BLOCK),
126 (ErrorKind::InvalidInput, blaze_err::INVALID_INPUT),
127 (ErrorKind::InvalidData, blaze_err::INVALID_DATA),
128 (ErrorKind::InvalidDwarf, blaze_err::INVALID_DWARF),
129 (ErrorKind::TimedOut, blaze_err::TIMED_OUT),
130 (ErrorKind::WriteZero, blaze_err::WRITE_ZERO),
131 (ErrorKind::Unsupported, blaze_err::UNSUPPORTED),
132 (ErrorKind::UnexpectedEof, blaze_err::UNEXPECTED_EOF),
133 (ErrorKind::OutOfMemory, blaze_err::OUT_OF_MEMORY),
134 (ErrorKind::Other, blaze_err::OTHER),
135 ];
136
137 for (kind, expected) in data {
138 assert_eq!(blaze_err::from(kind), expected);
139 let cstr = unsafe { CStr::from_ptr(blaze_err_str(expected)) };
140 let expected = CStr::from_bytes_with_nul(kind.as_bytes()).unwrap();
141 assert_eq!(cstr, expected);
142 }
143 }
144}