bulletin_board_mathematica/
lib.rs1use std::time::Duration;
2use bulletin_board_client::{
3 adaptor::Pair, adaptor::VecShape, adaptor::VecVecShape, ArrayObject, DataType,
4};
5use wolfram_library_link::{self as wll, generate_loader, wstp};
6
7generate_loader!(load_dbgbb);
8
9#[wll::export(wstp)]
10fn set_addr(link: &mut wstp::Link) {
11 assert_eq!(link.test_head("System`List").unwrap(), 1);
12 let addr = link.get_string().unwrap();
13 bulletin_board_client::set_addr(&addr);
14 link.put_str("Server address updated").unwrap();
15}
16
17#[wll::export(wstp)]
18fn set_timeout(link: &mut wstp::Link) {
19 let argc = link.test_head("System`List").unwrap();
20 match argc {
21 0 => bulletin_board_client::set_timeout(None),
22 1 => {
23 let timeout = link.get_i64().unwrap();
24 bulletin_board_client::set_timeout(Some(Duration::from_millis(
25 timeout.try_into().unwrap(),
26 )));
27 }
28 _ => panic!(),
29 };
30
31 link.put_str("Server address updated").unwrap();
32}
33
34#[wll::export(wstp)]
35fn post_integer(link: &mut wstp::Link) {
36 assert_eq!(link.test_head("System`List").unwrap(), 3);
37 let title = link.get_string().unwrap();
38 let tag = link.get_string().unwrap();
39 let val = link.get_i64().unwrap();
40 let obj = val.try_into().unwrap();
41 bulletin_board_client::post(&title, &tag, obj).unwrap();
42 link.put_str("Sent").unwrap();
43}
44
45#[wll::export(wstp)]
46fn post_real(link: &mut wstp::Link) {
47 assert_eq!(link.test_head("System`List").unwrap(), 3);
48 let title = link.get_string().unwrap();
49 let tag = link.get_string().unwrap();
50 let val = link.get_f64().unwrap();
51 let obj = val.try_into().unwrap();
52 bulletin_board_client::post(&title, &tag, obj).unwrap();
53 link.put_str("Sent").unwrap();
54}
55
56#[wll::export(wstp)]
57fn post_complex(link: &mut wstp::Link) {
58 assert_eq!(link.test_head("System`List").unwrap(), 4);
59 let title = link.get_string().unwrap();
60 let tag = link.get_string().unwrap();
61 let re = link.get_f64().unwrap();
62 let im = link.get_f64().unwrap();
63 let obj = Pair(re, im).try_into().unwrap();
64 bulletin_board_client::post(&title, &tag, obj).unwrap();
65 link.put_str("Sent").unwrap();
66}
67
68#[wll::export(wstp)]
69fn post_string(link: &mut wstp::Link) {
70 assert_eq!(link.test_head("System`List").unwrap(), 3);
71 let title = link.get_string().unwrap();
72 let tag = link.get_string().unwrap();
73 let val = link.get_string().unwrap();
74 let obj = val.try_into().unwrap();
75 bulletin_board_client::post(&title, &tag, obj).unwrap();
76 link.put_str("Sent").unwrap();
77}
78
79#[wll::export(wstp)]
80fn post_integer_array(link: &mut wstp::Link) {
81 assert_eq!(link.test_head("System`List").unwrap(), 3);
82 {
83 let title = link.get_string().unwrap();
84 let tag = link.get_string().unwrap();
85 let arr = link.get_i64_array().unwrap();
86 let shape = arr.dimensions().into_iter().map(|&x| x as u64).collect();
87 let data = arr.data().into_iter().copied().collect();
88 let obj = VecShape(data, shape).try_into().unwrap();
89 bulletin_board_client::post(&title, &tag, obj).unwrap();
90 }
91 link.put_str("Sent").unwrap();
92}
93
94#[wll::export(wstp)]
95fn post_real_array(link: &mut wstp::Link) {
96 assert_eq!(link.test_head("System`List").unwrap(), 3);
97 {
98 let title = link.get_string().unwrap();
99 let tag = link.get_string().unwrap();
100 let arr = link.get_f64_array().unwrap();
101 let shape = arr.dimensions().into_iter().map(|&x| x as u64).collect();
102 let data = arr.data().into_iter().copied().collect();
103 let obj = VecShape(data, shape).try_into().unwrap();
104 bulletin_board_client::post(&title, &tag, obj).unwrap();
105 }
106 link.put_str("Sent").unwrap();
107}
108
109#[wll::export(wstp)]
110fn post_complex_array(link: &mut wstp::Link) {
111 assert_eq!(link.test_head("System`List").unwrap(), 4);
112 {
113 let title = link.get_string().unwrap();
114 let tag = link.get_string().unwrap();
115 let (re, shape) = {
116 let re_arr = link.get_f64_array().unwrap();
117 let re = re_arr.data().into_iter().copied().collect();
118 let shape = re_arr.dimensions().into_iter().map(|&x| x as u64).collect();
119 (re, shape)
120 };
121 let im = {
122 let im_arr = link.get_f64_array().unwrap();
123 im_arr.data().into_iter().copied().collect()
124 };
125 let obj = VecVecShape(re, im, shape).try_into().unwrap();
126 bulletin_board_client::post(&title, &tag, obj).unwrap();
127 }
128 link.put_str("Sent").unwrap();
129}
130
131#[wll::export(wstp)]
132fn post_string_array(link: &mut wstp::Link) {
133 assert_eq!(link.test_head("System`List").unwrap(), 4);
134 {
135 let title = link.get_string().unwrap();
136 let tag = link.get_string().unwrap();
137 let len = link.test_head("System`List").unwrap();
138 let mut data = vec![];
139 for _ in 0..len {
140 let text = link.get_string().unwrap();
141 data.push(text);
142 }
143 let shape = link
144 .get_i64_array()
145 .unwrap()
146 .data()
147 .into_iter()
148 .map(|&x| x.try_into().unwrap())
149 .collect();
150 let obj = VecShape(data, shape).try_into().unwrap();
151 bulletin_board_client::post(&title, &tag, obj).unwrap();
152 }
153 link.put_str("Sent").unwrap();
154}
155
156#[wll::export(wstp)]
157fn read(link: &mut wstp::Link) {
158 let argc = link.test_head("System`List").unwrap();
159 let (title, tag, revisions) = match argc {
160 1 => (link.get_string().unwrap(), None, vec![]),
161 2 => {
162 let title = link.get_string().unwrap();
163 if link.get_type().unwrap() == wstp::TokenType::String {
164 (title, Some(link.get_string().unwrap()), vec![])
165 } else {
166 if link.get_type().unwrap() == wstp::TokenType::Integer {
167 (
168 title,
169 None,
170 vec![link.get_i64().unwrap().try_into().unwrap()],
171 )
172 } else {
173 (
174 title,
175 None,
176 link.get_i64_array()
177 .unwrap()
178 .data()
179 .into_iter()
180 .map(|&x| x.try_into().unwrap())
181 .collect(),
182 )
183 }
184 }
185 }
186 3 => {
187 let title = link.get_string().unwrap();
188 let tag = Some(link.get_string().unwrap());
189 if link.get_type().unwrap() == wstp::TokenType::Integer {
190 (
191 title,
192 tag,
193 vec![link.get_i64().unwrap().try_into().unwrap()],
194 )
195 } else {
196 (
197 title,
198 tag,
199 link.get_i64_array()
200 .unwrap()
201 .data()
202 .into_iter()
203 .map(|&x| x.try_into().unwrap())
204 .collect(),
205 )
206 }
207 }
208 _ => panic!(),
209 };
210 let list = bulletin_board_client::read(&title, tag.as_deref(), revisions).unwrap();
211 if list.len() > 1 {
212 link.put_function("System`List", list.len()).unwrap();
213 }
214 for data in list {
215 put_data(link, data);
216 }
217}
218
219fn put_data(link: &mut wstp::Link, data: ArrayObject) {
220 match data.datatype() {
221 DataType::UnsignedInteger | DataType::SignedInteger => {
222 if data.dimension() == 0 {
223 let val = data.try_into().unwrap();
224 link.put_i64(val).unwrap();
225 } else {
226 let VecShape(val, shape) = data.try_into().unwrap();
227 let shape: Vec<usize> = shape.into_iter().map(|x| x.try_into().unwrap()).collect();
228 link.put_i64_array(&val, &shape).unwrap();
229 }
230 }
231 DataType::Real => {
232 if data.dimension() == 0 {
233 let val = data.try_into().unwrap();
234 link.put_f64(val).unwrap();
235 } else {
236 let VecShape(val, shape) = data.try_into().unwrap();
237 let shape: Vec<usize> = shape.into_iter().map(|x| x.try_into().unwrap()).collect();
238 link.put_f64_array(&val, &shape).unwrap();
239 }
240 }
241 DataType::Complex => {
242 if data.dimension() == 0 {
243 let Pair(re, im) = data.try_into().unwrap();
244 link.put_function("System`Complex", 2).unwrap();
245 link.put_f64(re).unwrap();
246 link.put_f64(im).unwrap();
247 } else {
248 let VecVecShape(re, im, shape) = data.try_into().unwrap();
249 link.put_function("System`ArrayReshape", 2).unwrap();
250 link.put_function("System`List", re.len()).unwrap();
251 for (re, im) in re.into_iter().zip(im.into_iter()) {
252 link.put_function("System`Complex", 2).unwrap();
253 link.put_f64(re).unwrap();
254 link.put_f64(im).unwrap();
255 }
256 link.put_function("System`List", shape.len()).unwrap();
257 for d in shape {
258 link.put_i64(d.try_into().unwrap()).unwrap();
259 }
260 }
261 }
262 DataType::String => {
263 if data.dimension() == 0 {
264 let val: String = data.try_into().unwrap();
265 link.put_str(&val).unwrap();
266 } else {
267 let VecShape::<String>(val, shape) = data.try_into().unwrap();
268 link.put_function("System`ArrayReshape", 2).unwrap();
269 link.put_function("System`List", val.len()).unwrap();
270 for s in val {
271 link.put_str(&s).unwrap();
272 }
273 link.put_function("System`List", shape.len()).unwrap();
274 for d in shape {
275 link.put_i64(d.try_into().unwrap()).unwrap();
276 }
277 }
278 }
279 }
280}
281
282#[wll::export(wstp)]
283fn relabel(link: &mut wstp::Link) {
284 assert_eq!(link.test_head("System`List").unwrap(), 4);
285 let title_from = link.get_string().unwrap();
286 let tag_from = link.get_string().unwrap();
287 let title_to = link.get_string().unwrap();
288 let tag_to = link.get_string().unwrap();
289 let tag_from = match tag_from.as_str() {
290 "" => None,
291 _ => Some(tag_from.as_str()),
292 };
293 let title_to = match title_to.as_str() {
294 "" => None,
295 _ => Some(title_to.as_str()),
296 };
297 let tag_to = match tag_to.as_str() {
298 "" => None,
299 _ => Some(tag_to.as_str()),
300 };
301 bulletin_board_client::relabel(&title_from, tag_from, title_to, tag_to).unwrap();
302 link.put_str("Sent").unwrap();
303}
304
305#[wll::export(wstp)]
306fn client_version(link: &mut wstp::Link) {
307 assert_eq!(link.test_head("System`List").unwrap(), 0);
308 let client_version = env!("CARGO_PKG_VERSION").to_string();
309 link.put_str(&client_version).unwrap();
310}
311
312#[wll::export(wstp)]
313fn server_version(link: &mut wstp::Link) {
314 assert_eq!(link.test_head("System`List").unwrap(), 0);
315 let server_version = bulletin_board_client::server_version().unwrap();
316 link.put_str(&server_version).unwrap();
317}
318
319#[wll::export(wstp)]
320fn status(link: &mut wstp::Link) {
321 assert_eq!(link.test_head("System`List").unwrap(), 0);
322 let (datasize, memory_used, memory_used_percent, n_bulletins, n_files, n_archives) =
323 bulletin_board_client::status().unwrap();
324 link.put_function("System`List", 6).unwrap();
325 link.put_i64(datasize.try_into().unwrap()).unwrap();
326 link.put_i64(memory_used.try_into().unwrap()).unwrap();
327 link.put_f64(memory_used_percent).unwrap();
328 link.put_i64(n_bulletins.try_into().unwrap()).unwrap();
329 link.put_i64(n_files.try_into().unwrap()).unwrap();
330 link.put_i64(n_archives.try_into().unwrap()).unwrap();
331}
332
333#[wll::export(wstp)]
334fn log(link: &mut wstp::Link) {
335 assert_eq!(link.test_head("System`List").unwrap(), 0);
336 let log = bulletin_board_client::log().unwrap();
337 link.put_str(&log).unwrap();
338}
339
340#[wll::export(wstp)]
341fn view_board(link: &mut wstp::Link) {
342 assert_eq!(link.test_head("System`List").unwrap(), 0);
343 let board = bulletin_board_client::view_board().unwrap();
344 link.put_function("System`List", board.len()).unwrap();
345 for (title, tag, revisions) in board {
346 link.put_function("System`List", 3).unwrap();
347 link.put_str(&title).unwrap();
348 link.put_str(&tag).unwrap();
349 link.put_i64(revisions.try_into().unwrap()).unwrap();
350 }
351}
352
353#[wll::export(wstp)]
354fn get_info(link: &mut wstp::Link) {
355 let argc = link.test_head("System`List").unwrap();
356 let (title, tag) = match argc {
357 1 => (link.get_string().unwrap(), None),
358 2 => (link.get_string().unwrap(), Some(link.get_string().unwrap())),
359 _ => panic!(),
360 };
361 let info = bulletin_board_client::get_info(&title, tag.as_deref()).unwrap();
362 link.put_function("System`List", info.len()).unwrap();
363 for (revision, datasize, timestamp, backend) in info {
364 link.put_function("System`List", 4).unwrap();
365 link.put_i64(revision.try_into().unwrap()).unwrap();
366 link.put_i64(datasize.try_into().unwrap()).unwrap();
367 link.put_str(×tamp).unwrap();
368 link.put_str(&backend).unwrap();
369 }
370}
371
372#[wll::export(wstp)]
373fn clear_revisions(link: &mut wstp::Link) {
374 let argc = link.test_head("System`List").unwrap();
375 let (title, tag) = match argc {
376 2 => (link.get_string().unwrap(), None),
377 3 => (link.get_string().unwrap(), Some(link.get_string().unwrap())),
378 _ => panic!(),
379 };
380 if link.get_type().unwrap() == wstp::TokenType::Integer {
381 let revision = link.get_i64().unwrap().try_into().unwrap();
382 bulletin_board_client::clear_revisions(&title, tag.as_deref(), vec![revision]).unwrap();
383 } else {
384 let revisions = link
385 .get_i64_array()
386 .unwrap()
387 .data()
388 .into_iter()
389 .map(|&x| x.try_into().unwrap())
390 .collect();
391 bulletin_board_client::clear_revisions(&title, tag.as_deref(), revisions).unwrap();
392 }
393 link.put_str("Sent").unwrap();
394}
395
396#[wll::export(wstp)]
397fn remove(link: &mut wstp::Link) {
398 let argc = link.test_head("System`List").unwrap();
399 let (title, tag) = match argc {
400 1 => (link.get_string().unwrap(), None),
401 2 => (link.get_string().unwrap(), Some(link.get_string().unwrap())),
402 _ => panic!(),
403 };
404 bulletin_board_client::remove(&title, tag.as_deref()).unwrap();
405 link.put_str("Sent").unwrap();
406}
407
408#[wll::export(wstp)]
409fn archive(link: &mut wstp::Link) {
410 let argc = link.test_head("System`List").unwrap();
411 let acv_name = link.get_string().unwrap();
412 let (title, tag) = match argc {
413 2 => (link.get_string().unwrap(), None),
414 3 => (link.get_string().unwrap(), Some(link.get_string().unwrap())),
415 _ => panic!(),
416 };
417 bulletin_board_client::archive(&acv_name, &title, tag.as_deref()).unwrap();
418 link.put_str("Sent").unwrap();
419}
420
421#[wll::export(wstp)]
422fn load(link: &mut wstp::Link) {
423 assert_eq!(link.test_head("System`List").unwrap(), 1);
424 let acv_name = link.get_string().unwrap();
425 bulletin_board_client::load(&acv_name).unwrap();
426 link.put_str("Sent").unwrap();
427}
428
429#[wll::export(wstp)]
430fn list_archive(link: &mut wstp::Link) {
431 assert_eq!(link.test_head("System`List").unwrap(), 0);
432 let list = bulletin_board_client::list_archive().unwrap();
433 link.put_function("System`List", list.len()).unwrap();
434 for name in list {
435 link.put_str(&name).unwrap();
436 }
437}
438
439#[wll::export(wstp)]
440fn rename_archive(link: &mut wstp::Link) {
441 assert_eq!(link.test_head("System`List").unwrap(), 2);
442 let name_from = link.get_string().unwrap();
443 let name_to = link.get_string().unwrap();
444 bulletin_board_client::rename_archive(&name_from, &name_to).unwrap();
445 link.put_str("Sent").unwrap();
446}
447
448#[wll::export(wstp)]
449fn delete_archive(link: &mut wstp::Link) {
450 assert_eq!(link.test_head("System`List").unwrap(), 1);
451 let acv_name = link.get_string().unwrap();
452 bulletin_board_client::delete_archive(&acv_name).unwrap();
453 link.put_str("Sent").unwrap();
454}
455
456#[wll::export(wstp)]
457fn dump(link: &mut wstp::Link) {
458 assert_eq!(link.test_head("System`List").unwrap(), 1);
459 let acv_name = link.get_string().unwrap();
460 bulletin_board_client::dump(&acv_name).unwrap();
461 link.put_str("Sent").unwrap();
462}
463
464#[wll::export(wstp)]
465fn restore(link: &mut wstp::Link) {
466 assert_eq!(link.test_head("System`List").unwrap(), 1);
467 let acv_name = link.get_string().unwrap();
468 bulletin_board_client::restore(&acv_name).unwrap();
469 link.put_str("Sent").unwrap();
470}
471
472#[wll::export(wstp)]
473fn clear_log(link: &mut wstp::Link) {
474 assert_eq!(link.test_head("System`List").unwrap(), 0);
475 bulletin_board_client::clear_log().unwrap();
476 link.put_str("Sent").unwrap();
477}
478
479#[wll::export(wstp)]
480fn reset_server(link: &mut wstp::Link) {
481 assert_eq!(link.test_head("System`List").unwrap(), 0);
482 bulletin_board_client::reset_server().unwrap();
483 link.put_str("Sent").unwrap();
484}
485
486#[wll::export(wstp)]
487fn terminate_server(link: &mut wstp::Link) {
488 assert_eq!(link.test_head("System`List").unwrap(), 0);
489 bulletin_board_client::terminate_server().unwrap();
490 link.put_str("Sent").unwrap();
491}