11use 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
67use 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
2742const EMPTY : & CStr = c"" ;
@@ -34,12 +49,12 @@ thread_local! {
3449
3550pub 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) ]
61297mod 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