bulletin_board_client/
lib.rs

1use bbclient::{DataType, adaptor::VecShape};
2use num_complex::Complex64;
3use pyo3::prelude::*;
4use std::time::Duration;
5
6/// Sets the server address.
7#[pyfunction]
8fn set_addr(addr: String) -> PyResult<()> {
9    bbclient::set_addr(&addr);
10    Ok(())
11}
12
13/// Sets timeout for TCP connections in msec. If the argument is None, timeout is disabled (default).
14#[pyfunction]
15#[pyo3(signature = (timeout=None))]
16fn set_timeout(timeout: Option<u64>) -> PyResult<()> {
17    bbclient::set_timeout(timeout.map(|t| Duration::from_millis(t)));
18    Ok(())
19}
20
21#[pyfunction]
22fn post_integer(title: String, tag: String, val: i128) -> PyResult<()> {
23    let obj = val.try_into().unwrap();
24    bbclient::post(&title, &tag, obj).unwrap();
25    Ok(())
26}
27
28#[pyfunction]
29fn post_real(title: String, tag: String, val: f64) -> PyResult<()> {
30    let obj = val.try_into().unwrap();
31    bbclient::post(&title, &tag, obj).unwrap();
32    Ok(())
33}
34
35#[pyfunction]
36fn post_complex(title: String, tag: String, val: Complex64) -> PyResult<()> {
37    let obj = val.try_into().unwrap();
38    bbclient::post(&title, &tag, obj).unwrap();
39    Ok(())
40}
41
42#[pyfunction]
43fn post_string(title: String, tag: String, val: String) -> PyResult<()> {
44    let obj = val.try_into().unwrap();
45    bbclient::post(&title, &tag, obj).unwrap();
46    Ok(())
47}
48
49#[pyfunction]
50fn post_integer_array(title: String, tag: String, val: Vec<i128>, shape: Vec<u64>) -> PyResult<()> {
51    let obj = VecShape(val, shape).try_into().unwrap();
52    bbclient::post(&title, &tag, obj).unwrap();
53    Ok(())
54}
55
56#[pyfunction]
57fn post_real_array(title: String, tag: String, val: Vec<f64>, shape: Vec<u64>) -> PyResult<()> {
58    let obj = VecShape(val, shape).try_into().unwrap();
59    bbclient::post(&title, &tag, obj).unwrap();
60    Ok(())
61}
62
63#[pyfunction]
64fn post_complex_array(
65    title: String,
66    tag: String,
67    val: Vec<Complex64>,
68    shape: Vec<u64>,
69) -> PyResult<()> {
70    let obj = VecShape(val, shape).try_into().unwrap();
71    bbclient::post(&title, &tag, obj).unwrap();
72    Ok(())
73}
74
75#[pyfunction]
76fn post_string_array(
77    title: String,
78    tag: String,
79    val: Vec<String>,
80    shape: Vec<u64>,
81) -> PyResult<()> {
82    let obj = VecShape(val, shape).try_into().unwrap();
83    bbclient::post(&title, &tag, obj).unwrap();
84    Ok(())
85}
86
87#[pyfunction]
88#[pyo3(signature = (title, tag=None, revisions=None))]
89fn read_raw(
90    py: Python<'_>,
91    title: String,
92    tag: Option<String>,
93    revisions: Option<Vec<u64>>,
94) -> PyResult<PyObject> {
95    let revisions = match revisions {
96        Some(rev) => rev,
97        None => vec![],
98    };
99
100    let list = bbclient::read(&title, tag.as_deref(), revisions).unwrap();
101    let mut res: Vec<PyObject> = vec![];
102    for elem in list {
103        match elem.datatype() {
104            DataType::UnsignedInteger => {
105                if elem.dimension() == 0 {
106                    let val: u128 = elem.try_into().unwrap();
107                    res.push(val.into_pyobject(py).unwrap().into());
108                } else {
109                    let VecShape::<u128>(val, shape) = elem.try_into().unwrap();
110                    let shape: Vec<usize> =
111                        shape.into_iter().map(|x| x.try_into().unwrap()).collect();
112                    res.push((val, shape).into_pyobject(py).unwrap().into());
113                }
114            }
115            DataType::SignedInteger => {
116                if elem.dimension() == 0 {
117                    let val: i128 = elem.try_into().unwrap();
118                    res.push(val.into_pyobject(py).unwrap().into());
119                } else {
120                    let VecShape::<i128>(val, shape) = elem.try_into().unwrap();
121                    let shape: Vec<usize> =
122                        shape.into_iter().map(|x| x.try_into().unwrap()).collect();
123                    res.push((val, shape).into_pyobject(py).unwrap().into());
124                }
125            }
126            DataType::Real => {
127                if elem.dimension() == 0 {
128                    let val: f64 = elem.try_into().unwrap();
129                    res.push(val.into_pyobject(py).unwrap().into());
130                } else {
131                    let VecShape::<f64>(val, shape) = elem.try_into().unwrap();
132                    let shape: Vec<usize> =
133                        shape.into_iter().map(|x| x.try_into().unwrap()).collect();
134                    res.push((val, shape).into_pyobject(py).unwrap().into());
135                }
136            }
137            DataType::Complex => {
138                if elem.dimension() == 0 {
139                    let val: Complex64 = elem.try_into().unwrap();
140                    res.push(val.into_pyobject(py).unwrap().into());
141                } else {
142                    let VecShape::<Complex64>(val, shape) = elem.try_into().unwrap();
143                    res.push((val, shape).into_pyobject(py).unwrap().into());
144                }
145            }
146            DataType::String => {
147                if elem.dimension() == 0 {
148                    let val: String = elem.try_into().unwrap();
149                    res.push(val.into_pyobject(py).unwrap().into());
150                } else {
151                    let VecShape::<String>(val, shape) = elem.try_into().unwrap();
152                    res.push((val, shape).into_pyobject(py).unwrap().into());
153                }
154            }
155        }
156    }
157    Ok(res.into_pyobject(py).unwrap().into())
158}
159
160/// Relabels a bulletin.
161#[pyfunction]
162#[pyo3(signature = (title_from, tag_from=None, title_to=None, tag_to=None))]
163fn relabel(
164    title_from: String,
165    tag_from: Option<String>,
166    title_to: Option<String>,
167    tag_to: Option<String>,
168) -> PyResult<()> {
169    bbclient::relabel(
170        &title_from,
171        tag_from.as_deref(),
172        title_to.as_deref(),
173        tag_to.as_deref(),
174    )
175    .unwrap();
176    Ok(())
177}
178
179/// Returns the version of the client.
180#[pyfunction]
181fn client_version(py: Python<'_>) -> PyResult<PyObject> {
182    let client_version = env!("CARGO_PKG_VERSION").to_string();
183    Ok(client_version.into_pyobject(py).unwrap().into())
184}
185
186/// Returns the version of the server.
187#[pyfunction]
188fn server_version(py: Python<'_>) -> PyResult<PyObject> {
189    let server_version = bbclient::server_version().unwrap();
190    Ok(server_version.into_pyobject(py).unwrap().into())
191}
192
193/// Returns the status of the server.
194#[pyfunction]
195fn status_raw(py: Python<'_>) -> PyResult<PyObject> {
196    Ok(bbclient::status()
197        .unwrap()
198        .into_pyobject(py)
199        .unwrap()
200        .into())
201}
202
203/// Returns the log of the server.
204#[pyfunction]
205fn log(py: Python<'_>) -> PyResult<PyObject> {
206    Ok(bbclient::log().unwrap().into_pyobject(py).unwrap().into())
207}
208
209#[pyfunction]
210fn view_board_raw(py: Python<'_>) -> PyResult<PyObject> {
211    Ok(bbclient::view_board()
212        .unwrap()
213        .into_pyobject(py)
214        .unwrap()
215        .into())
216}
217
218#[pyfunction]
219#[pyo3(signature = (title, tag=None))]
220fn get_info_raw(py: Python<'_>, title: String, tag: Option<String>) -> PyResult<PyObject> {
221    Ok(bbclient::get_info(&title, tag.as_deref())
222        .unwrap()
223        .into_pyobject(py)
224        .unwrap()
225        .into())
226}
227
228#[pyfunction]
229#[pyo3(signature = (title, revisions, tag=None))]
230fn clear_revisions_raw(title: String, revisions: Vec<u64>, tag: Option<String>) -> PyResult<()> {
231    bbclient::clear_revisions(&title, tag.as_deref(), revisions).unwrap();
232    Ok(())
233}
234
235/// Removes all the revisions and the database entry of a bulletin.
236#[pyfunction]
237#[pyo3(signature = (title, tag=None))]
238fn remove(title: String, tag: Option<String>) -> PyResult<()> {
239    bbclient::remove(&title, tag.as_deref()).unwrap();
240    Ok(())
241}
242
243/// Moves a bulletin to a persistent archive.
244#[pyfunction]
245#[pyo3(signature = (acv_name, title, tag=None))]
246fn archive(acv_name: String, title: String, tag: Option<String>) -> PyResult<()> {
247    bbclient::archive(&acv_name, &title, tag.as_deref()).unwrap();
248    Ok(())
249}
250
251/// Loads or reloads an archive. The data is directly read from the archive file and a suffix "acv_name:" is added to the tag.
252#[pyfunction]
253fn load(acv_name: String) -> PyResult<()> {
254    bbclient::load(&acv_name).unwrap();
255    Ok(())
256}
257
258/// Shows the list of archive.
259#[pyfunction]
260fn list_archive(py: Python<'_>) -> PyResult<PyObject> {
261    Ok(bbclient::list_archive()
262        .unwrap()
263        .into_pyobject(py)
264        .unwrap()
265        .into())
266}
267
268/// Renames an archive. This will be applied after after calling reset_server.
269#[pyfunction]
270fn rename_archive(name_from: String, name_to: String) -> PyResult<()> {
271    bbclient::rename_archive(&name_from, &name_to).unwrap();
272    Ok(())
273}
274
275/// Deletes an archive. This will be applied after after calling reset_server.
276#[pyfunction]
277fn delete_archive(acv_name: String) -> PyResult<()> {
278    bbclient::delete_archive(&acv_name).unwrap();
279    Ok(())
280}
281
282/// Dumps all the unarchived data into an archive.
283#[pyfunction]
284fn dump(acv_name: String) -> PyResult<()> {
285    bbclient::dump(&acv_name).unwrap();
286    Ok(())
287}
288
289/// Delete all the temporary data and restores data from an archive. Each data is copied to memory or a separate file. No suffix is added to the tag.
290#[pyfunction]
291fn restore(acv_name: String) -> PyResult<()> {
292    bbclient::restore(&acv_name).unwrap();
293    Ok(())
294}
295
296/// Clears the log file of the server.
297#[pyfunction]
298fn clear_log() -> PyResult<()> {
299    bbclient::clear_log().unwrap();
300    Ok(())
301}
302
303/// Resets and clears the data. The archived data is not affected, but must be loaded before use.
304#[pyfunction]
305fn reset_server() -> PyResult<()> {
306    bbclient::reset_server().unwrap();
307    Ok(())
308}
309
310/// Terminates the server.
311#[pyfunction]
312fn terminate_server() -> PyResult<()> {
313    bbclient::terminate_server().unwrap();
314    Ok(())
315}
316
317/// BulletinBoard python client
318#[pymodule]
319fn bulletin_board_client(m: &Bound<'_, PyModule>) -> PyResult<()> {
320    m.add_function(wrap_pyfunction!(set_addr, m)?)?;
321    m.add_function(wrap_pyfunction!(set_timeout, m)?)?;
322    m.add_function(wrap_pyfunction!(post_integer, m)?)?;
323    m.add_function(wrap_pyfunction!(post_real, m)?)?;
324    m.add_function(wrap_pyfunction!(post_complex, m)?)?;
325    m.add_function(wrap_pyfunction!(post_string, m)?)?;
326    m.add_function(wrap_pyfunction!(post_integer_array, m)?)?;
327    m.add_function(wrap_pyfunction!(post_real_array, m)?)?;
328    m.add_function(wrap_pyfunction!(post_complex_array, m)?)?;
329    m.add_function(wrap_pyfunction!(post_string_array, m)?)?;
330    m.add_function(wrap_pyfunction!(read_raw, m)?)?;
331    m.add_function(wrap_pyfunction!(relabel, m)?)?;
332    m.add_function(wrap_pyfunction!(client_version, m)?)?;
333    m.add_function(wrap_pyfunction!(server_version, m)?)?;
334    m.add_function(wrap_pyfunction!(status_raw, m)?)?;
335    m.add_function(wrap_pyfunction!(log, m)?)?;
336    m.add_function(wrap_pyfunction!(view_board_raw, m)?)?;
337    m.add_function(wrap_pyfunction!(get_info_raw, m)?)?;
338    m.add_function(wrap_pyfunction!(clear_revisions_raw, m)?)?;
339    m.add_function(wrap_pyfunction!(remove, m)?)?;
340    m.add_function(wrap_pyfunction!(archive, m)?)?;
341    m.add_function(wrap_pyfunction!(load, m)?)?;
342    m.add_function(wrap_pyfunction!(list_archive, m)?)?;
343    m.add_function(wrap_pyfunction!(rename_archive, m)?)?;
344    m.add_function(wrap_pyfunction!(delete_archive, m)?)?;
345    m.add_function(wrap_pyfunction!(dump, m)?)?;
346    m.add_function(wrap_pyfunction!(restore, m)?)?;
347    m.add_function(wrap_pyfunction!(clear_log, m)?)?;
348    m.add_function(wrap_pyfunction!(reset_server, m)?)?;
349    m.add_function(wrap_pyfunction!(terminate_server, m)?)?;
350    Ok(())
351}