Skip to content

Commit 1777767

Browse files
committed
refactor(sys): add Error and MaybeError
1 parent ea10bc1 commit 1777767

File tree

2 files changed

+292
-70
lines changed

2 files changed

+292
-70
lines changed

taos-ws-sys/src/native/error.rs

Lines changed: 254 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,42 @@
11
use std::cell::RefCell;
2-
use std::ffi::{c_char, c_int, CStr};
2+
use std::ffi::{c_char, c_int, CStr, CString};
33

4-
use taos_error::Error;
4+
use taos_error::Code;
5+
use tracing::trace;
56

67
use super::TAOS_RES;
78

89
#[no_mangle]
9-
pub extern "C" fn taos_errno(res: *mut TAOS_RES) -> c_int {
10+
pub unsafe extern "C" fn taos_errno(res: *mut TAOS_RES) -> c_int {
1011
if res.is_null() {
1112
return errno();
1213
}
13-
todo!()
14+
15+
match (res as *mut MaybeError<()>)
16+
.as_ref()
17+
.and_then(MaybeError::errno)
18+
{
19+
Some(errno) => format_errno(errno),
20+
_ => Code::SUCCESS.into(),
21+
}
1422
}
1523

1624
#[no_mangle]
17-
pub extern "C" fn taos_errstr(res: *mut TAOS_RES) -> *const c_char {
25+
pub unsafe extern "C" fn taos_errstr(res: *mut TAOS_RES) -> *const c_char {
1826
if res.is_null() {
1927
if errno() == 0 {
2028
return EMPTY.as_ptr();
2129
}
2230
return errstr();
2331
}
24-
todo!()
32+
33+
match (res as *mut MaybeError<()>)
34+
.as_ref()
35+
.and_then(MaybeError::errstr)
36+
{
37+
Some(err) => err,
38+
_ => EMPTY.as_ptr(),
39+
}
2540
}
2641

2742
const EMPTY: &CStr = c"";
@@ -34,12 +49,12 @@ thread_local! {
3449

3550
pub fn set_err_and_get_code(err: Error) -> i32 {
3651
ERRNO.with(|errno| {
37-
let code: u32 = err.code().into();
52+
let code: u32 = err.code.into();
3853
*errno.borrow_mut() = (code | 0x80000000) as i32;
3954
});
4055

4156
ERRSTR.with(|errstr| {
42-
let bytes = err.message().into_bytes();
57+
let bytes = err.message.into_bytes();
4358
let len = bytes.len().min(MAX_ERRSTR_LEN - 1);
4459
let mut errstr = errstr.borrow_mut();
4560
errstr[..len].copy_from_slice(&bytes[..len]);
@@ -57,26 +72,247 @@ pub fn errstr() -> *const c_char {
5772
ERRSTR.with(|errstr| errstr.borrow().as_ptr() as _)
5873
}
5974

75+
pub fn format_errno(errno: i32) -> i32 {
76+
if errno >= 0 {
77+
return (errno as u32 | 0x80000000) as i32;
78+
}
79+
errno
80+
}
81+
82+
#[derive(Debug)]
83+
pub struct MaybeError<T> {
84+
err: Option<Error>,
85+
data: *mut T,
86+
type_id: &'static str,
87+
}
88+
89+
impl<T> MaybeError<T> {
90+
pub fn errno(&self) -> Option<i32> {
91+
self.err.as_ref().map(|err| err.code.into())
92+
}
93+
94+
pub fn errstr(&self) -> Option<*const c_char> {
95+
self.err.as_ref().map(|err| err.message.as_ptr())
96+
}
97+
98+
pub fn deref(&self) -> Option<&T> {
99+
unsafe { self.data.as_ref() }
100+
}
101+
102+
pub fn deref_mut(&self) -> Option<&mut T> {
103+
unsafe { self.data.as_mut() }
104+
}
105+
}
106+
107+
impl<T> Drop for MaybeError<T> {
108+
fn drop(&mut self) {
109+
if !self.data.is_null() {
110+
trace!("Dropping MaybeError, type_id: {}", self.type_id);
111+
let _ = unsafe { Box::from_raw(self.data) };
112+
}
113+
}
114+
}
115+
116+
impl<T> From<T> for MaybeError<T> {
117+
fn from(value: T) -> Self {
118+
Self {
119+
err: None,
120+
data: Box::into_raw(Box::new(value)),
121+
type_id: std::any::type_name::<T>(),
122+
}
123+
}
124+
}
125+
126+
impl<T> From<Box<T>> for MaybeError<T> {
127+
fn from(value: Box<T>) -> Self {
128+
Self {
129+
err: None,
130+
data: Box::into_raw(value),
131+
type_id: std::any::type_name::<T>(),
132+
}
133+
}
134+
}
135+
136+
impl<T, E> From<Result<T, E>> for MaybeError<T>
137+
where
138+
E: Into<Error>,
139+
{
140+
fn from(value: Result<T, E>) -> Self {
141+
match value {
142+
Ok(val) => Self {
143+
err: None,
144+
data: Box::into_raw(Box::new(val)),
145+
type_id: std::any::type_name::<T>(),
146+
},
147+
Err(err) => Self {
148+
err: Some(err.into()),
149+
data: std::ptr::null_mut(),
150+
type_id: std::any::type_name::<T>(),
151+
},
152+
}
153+
}
154+
}
155+
156+
impl<T, E> From<Result<Box<T>, E>> for MaybeError<T>
157+
where
158+
E: Into<Error>,
159+
{
160+
fn from(value: Result<Box<T>, E>) -> Self {
161+
match value {
162+
Ok(val) => Self {
163+
err: None,
164+
data: Box::into_raw(val),
165+
type_id: std::any::type_name::<T>(),
166+
},
167+
Err(err) => Self {
168+
err: Some(err.into()),
169+
data: std::ptr::null_mut(),
170+
type_id: std::any::type_name::<T>(),
171+
},
172+
}
173+
}
174+
}
175+
176+
#[derive(Debug)]
177+
pub struct Error {
178+
code: Code,
179+
message: CString,
180+
source: Option<Box<dyn std::error::Error>>,
181+
}
182+
183+
impl Error {
184+
pub fn new(code: Code, message: &str) -> Self {
185+
Self {
186+
code,
187+
message: CString::new(message).unwrap(),
188+
source: None,
189+
}
190+
}
191+
}
192+
193+
impl From<&Error> for Error {
194+
fn from(err: &Error) -> Self {
195+
Self {
196+
code: err.code,
197+
message: err.message.clone(),
198+
source: None,
199+
}
200+
}
201+
}
202+
203+
impl std::fmt::Display for Error {
204+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205+
write!(f, "[{:#06X}] {}", self.code, self.message.to_str().unwrap())
206+
}
207+
}
208+
209+
impl std::error::Error for Error {
210+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
211+
self.source.as_ref().map(|e| e.as_ref())
212+
}
213+
}
214+
215+
impl From<Box<dyn std::error::Error>> for Error {
216+
fn from(err: Box<dyn std::error::Error>) -> Self {
217+
Self {
218+
code: Code::FAILED,
219+
message: CString::new(err.to_string()).unwrap(),
220+
source: Some(err),
221+
}
222+
}
223+
}
224+
225+
impl From<std::str::Utf8Error> for Error {
226+
fn from(err: std::str::Utf8Error) -> Self {
227+
Self {
228+
code: Code::FAILED,
229+
message: CString::new(err.to_string()).unwrap(),
230+
source: Some(Box::new(err)),
231+
}
232+
}
233+
}
234+
235+
impl From<std::string::FromUtf8Error> for Error {
236+
fn from(err: std::string::FromUtf8Error) -> Self {
237+
Self {
238+
code: Code::FAILED,
239+
message: CString::new(err.to_string()).unwrap(),
240+
source: Some(Box::new(err)),
241+
}
242+
}
243+
}
244+
245+
impl From<taos_query::DsnError> for Error {
246+
fn from(err: taos_query::DsnError) -> Self {
247+
use taos_ws::query::asyn::WS_ERROR_NO;
248+
Self {
249+
code: WS_ERROR_NO::DSN_ERROR.as_code(),
250+
message: CString::new(err.to_string()).unwrap(),
251+
source: None,
252+
}
253+
}
254+
}
255+
256+
impl From<taos_query::common::SmlDataBuilderError> for Error {
257+
fn from(err: taos_query::common::SmlDataBuilderError) -> Self {
258+
Self {
259+
code: Code::FAILED,
260+
message: CString::new(err.to_string()).unwrap(),
261+
source: Some(Box::new(err)),
262+
}
263+
}
264+
}
265+
266+
impl From<taos_ws::Error> for Error {
267+
fn from(e: taos_ws::Error) -> Self {
268+
Self {
269+
code: e.errno(),
270+
message: CString::new(e.errstr()).unwrap(),
271+
source: None,
272+
}
273+
}
274+
}
275+
276+
impl From<taos_ws::query::Error> for Error {
277+
fn from(err: taos_ws::query::Error) -> Self {
278+
Self {
279+
code: err.errno(),
280+
message: CString::new(err.errstr()).unwrap(),
281+
source: None,
282+
}
283+
}
284+
}
285+
286+
impl From<taos_error::Error> for Error {
287+
fn from(err: taos_error::Error) -> Self {
288+
Self {
289+
code: err.code(),
290+
message: CString::new(err.to_string()).unwrap(),
291+
source: None,
292+
}
293+
}
294+
}
295+
60296
#[cfg(test)]
61297
mod tests {
62298
use std::ffi::CStr;
63299
use std::ptr::null_mut;
64300

65-
use taos_error::Error;
66-
67301
use super::*;
68302

69303
#[test]
70304
fn test_set_err_and_get_code() {
71-
let err = Error::new(1, "test error");
72-
let code = set_err_and_get_code(err);
73-
assert_eq!(code as u32, 0x80000001);
305+
unsafe {
306+
let err = Error::new(Code::SUCCESS, "test error");
307+
let code = set_err_and_get_code(err);
308+
assert_eq!(code as u32, 0x80000000);
74309

75-
let code = taos_errno(null_mut());
76-
assert_eq!(code as u32, 0x80000001);
310+
let code = taos_errno(null_mut());
311+
assert_eq!(code as u32, 0x80000000);
77312

78-
let errstr_ptr = taos_errstr(null_mut());
79-
let errstr = unsafe { CStr::from_ptr(errstr_ptr) };
80-
assert_eq!(errstr, c"Internal error: `test error`"); // todo
313+
let errstr_ptr = taos_errstr(null_mut());
314+
let errstr = CStr::from_ptr(errstr_ptr);
315+
assert_eq!(errstr, c"test error");
316+
}
81317
}
82318
}

0 commit comments

Comments
 (0)