rtdlib_sys/lib.rs
1extern crate libc;
2
3use libc::{c_double, c_int, c_long, c_void};
4use std::ffi::CStr;
5use std::ffi::CString;
6use std::os::raw::c_char;
7use std::ptr;
8
9type TdlibClient = *mut c_void;
10
11#[derive(Debug)]
12pub struct Tdlib {
13 instance: TdlibClient,
14}
15
16unsafe impl Send for Tdlib {}
17unsafe impl Sync for Tdlib {}
18
19#[link(name = "tdjson")]
20extern "C" {
21 fn td_json_client_create() -> TdlibClient;
22 fn td_json_client_send(client: TdlibClient, request: *const c_char);
23 fn td_json_client_receive(client: TdlibClient, timeout: c_double) -> *mut c_char;
24 fn td_json_client_execute(client: TdlibClient, request: *const c_char) -> *mut c_char;
25 fn td_json_client_destroy(client: TdlibClient);
26
27 fn td_set_log_verbosity_level(level: c_int);
28 fn td_set_log_file_path(path: *const c_char) -> c_int;
29 fn td_set_log_max_file_size(size: c_long);
30}
31
32impl Tdlib {
33 /// Sets the verbosity level of the internal logging of TDLib.
34 ///
35 /// By default the TDLib uses a log verbosity level of 5.
36 ///
37 /// # Parameters
38 ///
39 /// `level` New value of logging verbosity level. Value 0 corresponds to fatal errors,
40 /// value 1 corresponds to errors, value 2 corresponds to warnings and debug warnings,
41 /// value 3 corresponds to informational, value 4 corresponds to debug, value 5 corresponds
42 /// to verbose debug, value greater than 5 and up to 1024 can be used to enable even more logging.
43 ///
44 /// # Examples
45 ///
46 /// ```
47 /// use rtdlib_sys::Tdlib;
48 /// Tdlib::set_log_verbosity_level(3);
49 /// ```
50 pub fn set_log_verbosity_level<'a>(level: i32) -> Result<(), &'a str> {
51 if level < 0 {
52 Err("log verbosity level should be >= 0")
53 } else if level > 1024 {
54 Err("log verbosity level should be <= 1024")
55 } else {
56 unsafe { td_set_log_verbosity_level(level) };
57 Ok(())
58 }
59 }
60
61 /// Sets maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated.
62 ///
63 /// Unused if log is not written to a file. Defaults to 10 MB.
64 ///
65 /// # Parameters
66 ///
67 /// `size` Maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated. Should be positive.
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use rtdlib_sys::Tdlib;
73 /// Tdlib::set_log_max_file_size(1024 * 1024);
74 /// ```
75 pub fn set_log_max_file_size(size: i64) {
76 unsafe { td_set_log_max_file_size(size as c_long) };
77 }
78
79 /// Sets the path to the file where the internal TDLib log will be written.
80 ///
81 /// By default TDLib writes logs to stderr or an OS specific log. Use this method to write the log to a file instead.
82 ///
83 /// # Parameters
84 ///
85 /// `path` Maybe path to a file where the internal TDLib log will be written. Use `None` to switch back to the default logging behaviour.
86 ///
87 /// # Examples
88 ///
89 /// ```
90 /// use rtdlib_sys::Tdlib;
91 /// Tdlib::set_log_file_path(Some("/var/log/tdlib/tdlib.log"));
92 /// ```
93 pub fn set_log_file_path(path: Option<&str>) -> bool {
94 let result = match path {
95 None => unsafe { td_set_log_file_path(ptr::null()) },
96 Some(path_) => {
97 let cpath = CString::new(path_).unwrap();
98 unsafe { td_set_log_file_path(cpath.as_ptr()) }
99 }
100 };
101 match result {
102 1 => true,
103 0 => false,
104 _ => panic!("unexpected response from libtdjson: {:?}", result)
105 }
106 }
107
108 /// Creates a new instance of TDLib.
109 ///
110 /// # Examples
111 ///
112 /// ```
113 /// use rtdlib_sys::Tdlib;
114 /// let tdlib = Tdlib::new();
115 /// ```
116 pub fn new() -> Self {
117 let client = unsafe { td_json_client_create() };
118 Tdlib { instance: client }
119 }
120
121 /// Sends request to the TDLib client.
122 ///
123 /// May be called from any thread.
124 ///
125 /// # Examples
126 ///
127 /// ```
128 /// use rtdlib_sys::Tdlib;
129 /// let tdlib = Tdlib::new();
130 /// let request = r#"{"@type": "getMe"}"#;
131 /// tdlib.send(request);
132 /// ```
133 pub fn send(&self, request: &str) {
134 let cstring = CString::new(request).unwrap();
135 unsafe { td_json_client_send(self.instance, cstring.as_ptr()) }
136 }
137
138 /// Synchronously executes TDLib request.
139 ///
140 /// May be called from any thread. Only a few requests can be executed synchronously.
141 ///
142 /// # Examples
143 ///
144 /// ```
145 /// use rtdlib_sys::Tdlib;
146 /// let tdlib = Tdlib::new();
147 /// let request = r#"{"@type": "getTextEntities", "text": "@telegram /test_command https://telegram.org telegram.me"}"#;
148 /// tdlib.execute(request);
149 /// ```
150 pub fn execute(&self, request: &str) -> Option<String> {
151 let cstring = CString::new(request).unwrap();
152 let result = unsafe {
153 td_json_client_execute(self.instance, cstring.as_ptr())
154 .as_ref()
155 .map(|response| CStr::from_ptr(response).to_string_lossy().into_owned())
156 };
157 result
158 }
159
160 /// Receives incoming updates and request responses from the TDLib client.
161 ///
162 /// May be called from any thread, but shouldn't be called simultaneously
163 /// from two different threads.
164 ///
165 /// # Examples
166 ///
167 /// ```
168 /// use rtdlib_sys::Tdlib;
169 /// let tdlib = Tdlib::new();
170 /// tdlib.receive(5.0);
171 /// ```
172 pub fn receive(&self, timeout: f64) -> Option<String> {
173// debug!("tdlib receive with timeout {}s", timeout);
174 unsafe {
175 match td_json_client_receive(self.instance, timeout)
176 .as_ref()
177 .map(|response| CStr::from_ptr(response).to_string_lossy().into_owned()) {
178 None => {
179 None
180 }
181 Some(contents) => {
182 Some(contents)
183 }
184 }
185 }
186 }
187}
188
189impl Drop for Tdlib {
190 fn drop(&mut self) {
191 unsafe {
192 td_json_client_destroy(self.instance);
193 }
194 }
195}