1use std::{
4 ffi::{CStr, CString},
5 os::raw::{c_char, c_double, c_int},
6};
7
8#[link(name = "tdjson")]
9extern "C" {
10 fn td_create_client_id() -> c_int;
11 fn td_send(client_id: c_int, request: *const c_char);
12 fn td_receive(timeout: c_double) -> *const c_char;
13 fn td_execute(request: *const c_char) -> *const c_char;
14}
15
16#[derive(Debug, Clone)]
17pub struct TDLib {
18 client_id: i32,
19}
20
21impl TDLib {
22 pub fn new() -> Self {
24 Self {
25 client_id: unsafe { td_create_client_id() },
26 }
27 }
28
29 pub fn send(&self, request: &str) {
33 let cstring = CString::new(request).unwrap();
34 unsafe { td_send(self.client_id, cstring.as_ptr()) }
35 }
36
37 pub fn execute(request: &str) -> Option<String> {
41 let cstring = CString::new(request).unwrap();
42 unsafe {
43 td_execute(cstring.as_ptr())
44 .as_ref()
45 .map(|response| CStr::from_ptr(response).to_string_lossy().into_owned())
46 }
47 }
48
49 pub fn receive(timeout: f64) -> Option<String> {
54 unsafe {
55 td_receive(timeout)
56 .as_ref()
57 .map(|response| CStr::from_ptr(response).to_string_lossy().into_owned())
58 }
59 }
60}
61
62impl Default for TDLib {
63 fn default() -> Self {
64 Self::new()
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::TDLib;
71
72 #[test]
73 fn test_execute() {
74 let result = TDLib::execute(
77 r#"{"@type":"setLogVerbosityLevel","new_verbosity_level":1,"@extra":1.01234}"#,
78 )
79 .unwrap();
80
81 assert_eq!(result, r#"{"@type":"ok","@extra":1.01234}"#);
82 }
83}