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);
41 pub const UNEXPECTED_EOF: blaze_err = blaze_err(-258);
44 pub const INVALID_DWARF: blaze_err = blaze_err(-259);
46 pub const OTHER: blaze_err = blaze_err(-260);
49}
50
51impl From<ErrorKind> for blaze_err {
52 fn from(other: ErrorKind) -> Self {
53 match other {
54 ErrorKind::NotFound => blaze_err::NOT_FOUND,
55 ErrorKind::PermissionDenied => blaze_err::PERMISSION_DENIED,
56 ErrorKind::AlreadyExists => blaze_err::ALREADY_EXISTS,
57 ErrorKind::WouldBlock => blaze_err::WOULD_BLOCK,
58 ErrorKind::InvalidInput => blaze_err::INVALID_INPUT,
59 ErrorKind::InvalidData => blaze_err::INVALID_DATA,
60 ErrorKind::InvalidDwarf => blaze_err::INVALID_DWARF,
61 ErrorKind::TimedOut => blaze_err::TIMED_OUT,
62 ErrorKind::WriteZero => blaze_err::WRITE_ZERO,
63 ErrorKind::Unsupported => blaze_err::UNSUPPORTED,
64 ErrorKind::UnexpectedEof => blaze_err::UNEXPECTED_EOF,
65 ErrorKind::OutOfMemory => blaze_err::OUT_OF_MEMORY,
66 ErrorKind::Other => blaze_err::OTHER,
67 _ => unreachable!(),
68 }
69 }
70}
71
72
73thread_local! {
74 static LAST_ERR: Cell<blaze_err> = const { Cell::new(blaze_err::OK) };
76}
77
78#[no_mangle]
80pub extern "C" fn blaze_err_last() -> blaze_err {
81 LAST_ERR.with(Cell::get)
82}
83
84pub(crate) fn set_last_err(err: blaze_err) {
86 LAST_ERR.with(|cell| cell.set(err))
87}
88
89
90#[no_mangle]
92pub extern "C" fn blaze_err_str(err: blaze_err) -> *const c_char {
93 match err {
94 blaze_err::OK => b"success\0".as_ptr().cast(),
95 blaze_err::NOT_FOUND => ErrorKind::NotFound.as_bytes().as_ptr().cast(),
96 blaze_err::PERMISSION_DENIED => ErrorKind::PermissionDenied.as_bytes().as_ptr().cast(),
97 blaze_err::ALREADY_EXISTS => ErrorKind::AlreadyExists.as_bytes().as_ptr().cast(),
98 blaze_err::WOULD_BLOCK => ErrorKind::WouldBlock.as_bytes().as_ptr().cast(),
99 blaze_err::INVALID_INPUT => ErrorKind::InvalidInput.as_bytes().as_ptr().cast(),
100 blaze_err::INVALID_DATA => ErrorKind::InvalidData.as_bytes().as_ptr().cast(),
101 blaze_err::INVALID_DWARF => ErrorKind::InvalidDwarf.as_bytes().as_ptr().cast(),
102 blaze_err::TIMED_OUT => ErrorKind::TimedOut.as_bytes().as_ptr().cast(),
103 blaze_err::WRITE_ZERO => ErrorKind::WriteZero.as_bytes().as_ptr().cast(),
104 blaze_err::UNSUPPORTED => ErrorKind::Unsupported.as_bytes().as_ptr().cast(),
105 blaze_err::UNEXPECTED_EOF => ErrorKind::UnexpectedEof.as_bytes().as_ptr().cast(),
106 blaze_err::OUT_OF_MEMORY => ErrorKind::OutOfMemory.as_bytes().as_ptr().cast(),
107 _ => ErrorKind::Other.as_bytes().as_ptr().cast(),
108 }
109}
110
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 use std::ffi::CStr;
117
118
119 #[test]
121 fn error_conversion() {
122 let data = [
123 (ErrorKind::NotFound, blaze_err::NOT_FOUND),
124 (ErrorKind::PermissionDenied, blaze_err::PERMISSION_DENIED),
125 (ErrorKind::AlreadyExists, blaze_err::ALREADY_EXISTS),
126 (ErrorKind::WouldBlock, blaze_err::WOULD_BLOCK),
127 (ErrorKind::InvalidInput, blaze_err::INVALID_INPUT),
128 (ErrorKind::InvalidData, blaze_err::INVALID_DATA),
129 (ErrorKind::InvalidDwarf, blaze_err::INVALID_DWARF),
130 (ErrorKind::TimedOut, blaze_err::TIMED_OUT),
131 (ErrorKind::WriteZero, blaze_err::WRITE_ZERO),
132 (ErrorKind::Unsupported, blaze_err::UNSUPPORTED),
133 (ErrorKind::UnexpectedEof, blaze_err::UNEXPECTED_EOF),
134 (ErrorKind::OutOfMemory, blaze_err::OUT_OF_MEMORY),
135 (ErrorKind::Other, blaze_err::OTHER),
136 ];
137
138 for (kind, expected) in data {
139 assert_eq!(blaze_err::from(kind), expected);
140 let cstr = unsafe { CStr::from_ptr(blaze_err_str(expected)) };
141 let expected = CStr::from_bytes_with_nul(kind.as_bytes()).unwrap();
142 assert_eq!(cstr, expected);
143 }
144 }
145}