Skip to content

Commit 9d1b912

Browse files
committed
refactor(sys): impl taos_connect, taos_errno and taos_errstr funcs
1 parent 030fc6a commit 9d1b912

File tree

3 files changed

+203
-14
lines changed

3 files changed

+203
-14
lines changed

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use std::cell::RefCell;
2+
use std::ffi::{c_char, c_int, CStr};
3+
4+
use taos_error::Error;
5+
6+
use super::TAOS_RES;
7+
8+
#[no_mangle]
9+
pub extern "C" fn taos_errno(res: *mut TAOS_RES) -> c_int {
10+
if res.is_null() {
11+
return errno();
12+
}
13+
todo!()
14+
}
15+
16+
#[no_mangle]
17+
pub extern "C" fn taos_errstr(res: *mut TAOS_RES) -> *const c_char {
18+
if res.is_null() {
19+
if errno() == 0 {
20+
return EMPTY.as_ptr();
21+
}
22+
return errstr();
23+
}
24+
todo!()
25+
}
26+
27+
const EMPTY: &CStr = c"";
28+
const MAX_ERRSTR_LEN: usize = 4096;
29+
30+
thread_local! {
31+
static ERRNO: RefCell<i32> = const { RefCell::new(0) };
32+
static ERRSTR: RefCell<[u8; MAX_ERRSTR_LEN]> = const { RefCell::new([0; MAX_ERRSTR_LEN]) };
33+
}
34+
35+
pub fn set_err_and_get_code(err: Error) -> i32 {
36+
ERRNO.with(|errno| {
37+
let code: u32 = err.code().into();
38+
*errno.borrow_mut() = (code | 0x80000000) as i32;
39+
});
40+
41+
ERRSTR.with(|errstr| {
42+
let bytes = err.message().into_bytes();
43+
let len = bytes.len().min(MAX_ERRSTR_LEN - 1);
44+
let mut errstr = errstr.borrow_mut();
45+
errstr[..len].copy_from_slice(&bytes[..len]);
46+
errstr[len] = 0;
47+
});
48+
49+
errno()
50+
}
51+
52+
pub fn errno() -> i32 {
53+
ERRNO.with(|errno| *errno.borrow())
54+
}
55+
56+
pub fn errstr() -> *const c_char {
57+
ERRSTR.with(|errstr| errstr.borrow().as_ptr() as _)
58+
}
59+
60+
#[cfg(test)]
61+
mod tests {
62+
use std::ffi::CStr;
63+
use std::ptr::null_mut;
64+
65+
use taos_error::Error;
66+
67+
use super::*;
68+
69+
#[test]
70+
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);
74+
75+
let code = taos_errno(null_mut());
76+
assert_eq!(code as u32, 0x80000001);
77+
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
81+
}
82+
}

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

Lines changed: 111 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
#![allow(unused_variables)]
22

3-
use std::ffi::{c_char, c_int, c_void};
3+
use std::ffi::{c_char, c_int, c_void, CStr};
4+
use std::ptr::null_mut;
45

6+
use error::set_err_and_get_code;
7+
use taos_error::{Code, Error};
8+
use taos_query::TBuilder;
9+
use taos_ws::{Taos, TaosBuilder};
10+
11+
mod error;
512
pub mod query;
613
pub mod sml;
714
pub mod stmt;
@@ -13,6 +20,8 @@ pub type TAOS = c_void;
1320
#[allow(non_camel_case_types)]
1421
pub type TAOS_RES = c_void;
1522

23+
type Result<T> = std::result::Result<T, Error>;
24+
1625
#[repr(C)]
1726
#[allow(non_camel_case_types)]
1827
pub enum TSDB_OPTION {
@@ -61,17 +70,77 @@ pub extern "C" fn taos_connect(
6170
db: *const c_char,
6271
port: u16,
6372
) -> *mut TAOS {
64-
todo!()
73+
match connect(ip, user, pass, db, port) {
74+
Ok(taos) => Box::into_raw(Box::new(taos)) as _,
75+
Err(err) => {
76+
set_err_and_get_code(err);
77+
null_mut()
78+
}
79+
}
6580
}
6681

67-
#[no_mangle]
68-
pub extern "C" fn taos_connect_dsn(
69-
dsn: *const c_char,
82+
fn connect(
83+
ip: *const c_char,
7084
user: *const c_char,
7185
pass: *const c_char,
7286
db: *const c_char,
73-
) -> *mut TAOS {
74-
todo!()
87+
mut port: u16,
88+
) -> Result<Taos> {
89+
const DEFAULT_IP: &str = "localhost";
90+
const DEFAULT_PORT: u16 = 6041;
91+
const DEFAULT_USER: &str = "root";
92+
const DEFAULT_PASS: &str = "taosdata";
93+
const DEFAULT_DB: &str = "";
94+
95+
let ip = if ip.is_null() {
96+
DEFAULT_IP
97+
} else {
98+
let ip = unsafe { CStr::from_ptr(ip) };
99+
match ip.to_str() {
100+
Ok(ip) => ip,
101+
Err(_) => return Err(Error::new(Code::INVALID_PARA, "Invalid ip")),
102+
}
103+
};
104+
105+
let user = if user.is_null() {
106+
DEFAULT_USER
107+
} else {
108+
let user = unsafe { CStr::from_ptr(user) };
109+
match user.to_str() {
110+
Ok(user) => user,
111+
Err(_) => return Err(Error::new(Code::INVALID_PARA, "Invalid user")),
112+
}
113+
};
114+
115+
let pass = if pass.is_null() {
116+
DEFAULT_PASS
117+
} else {
118+
let pass = unsafe { CStr::from_ptr(pass) };
119+
match pass.to_str() {
120+
Ok(pass) => pass,
121+
Err(_) => return Err(Error::new(Code::INVALID_PARA, "Invalid pass")),
122+
}
123+
};
124+
125+
let db = if db.is_null() {
126+
DEFAULT_DB
127+
} else {
128+
let db = unsafe { CStr::from_ptr(db) };
129+
match db.to_str() {
130+
Ok(db) => db,
131+
Err(_) => return Err(Error::new(Code::INVALID_PARA, "Invalid db")),
132+
}
133+
};
134+
135+
if port == 0 {
136+
port = DEFAULT_PORT;
137+
}
138+
139+
let dsn = format!("ws://{user}:{pass}@{ip}:{port}/{db}");
140+
let builder = TaosBuilder::from_dsn(dsn)?;
141+
let mut taos = builder.build()?;
142+
builder.ping(&mut taos)?;
143+
Ok(taos)
75144
}
76145

77146
#[no_mangle]
@@ -84,12 +153,40 @@ pub extern "C" fn taos_data_type(r#type: c_int) -> *const c_char {
84153
todo!()
85154
}
86155

87-
#[no_mangle]
88-
pub extern "C" fn taos_errstr(res: *mut TAOS_RES) -> *const c_char {
89-
todo!()
90-
}
156+
#[cfg(test)]
157+
mod tests {
158+
use std::ffi::CString;
159+
use std::ptr::null;
91160

92-
#[no_mangle]
93-
pub extern "C" fn taos_errno(res: *mut TAOS_RES) -> c_int {
94-
todo!()
161+
use super::*;
162+
163+
#[test]
164+
fn test_taos_connect() {
165+
let taos = taos_connect(
166+
c"localhost".as_ptr(),
167+
c"root".as_ptr(),
168+
c"taosdata".as_ptr(),
169+
null(),
170+
6041,
171+
);
172+
assert!(!taos.is_null());
173+
174+
let taos = taos_connect(null(), null(), null(), null(), 0);
175+
assert!(!taos.is_null());
176+
177+
let invalid_utf8 = CString::new([0xff, 0xfe, 0xfd]).unwrap();
178+
let invalid_utf8_ptr = invalid_utf8.as_ptr();
179+
180+
let taos = taos_connect(invalid_utf8_ptr, null(), null(), null(), 0);
181+
assert!(taos.is_null());
182+
183+
let taos = taos_connect(null(), invalid_utf8_ptr, null(), null(), 0);
184+
assert!(taos.is_null());
185+
186+
let taos = taos_connect(null(), null(), invalid_utf8_ptr, null(), 0);
187+
assert!(taos.is_null());
188+
189+
let taos = taos_connect(null(), null(), null(), invalid_utf8_ptr, 0);
190+
assert!(taos.is_null());
191+
}
95192
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ pub extern "C" fn taos_connect_auth(
2626
todo!("taos_connect_auth");
2727
}
2828

29+
#[no_mangle]
30+
pub extern "C" fn taos_connect_dsn(
31+
dsn: *const c_char,
32+
user: *const c_char,
33+
pass: *const c_char,
34+
db: *const c_char,
35+
) -> *mut TAOS {
36+
todo!("taos_connect_dsn");
37+
}
38+
2939
#[no_mangle]
3040
pub extern "C" fn taos_connect_dsn_auth(
3141
dsn: *const c_char,

0 commit comments

Comments
 (0)