1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use std::io::{self, Read, Write};
use std::fs::File;
use std::cell::RefCell;
use super::{ServiceOptions, FileOptions};
pub struct ServiceWorker {
output: File,
input: io::Stdin,
}
pub trait Handler {
fn on_message(&self, msg: &[u8]) -> std::io::Result<()>;
}
thread_local! {
static SERVICE: RefCell<Option<ServiceWorker>> = RefCell::new(None);
static HANDLER: RefCell<Option<Box<dyn Handler>>> = RefCell::new(None);
}
impl ServiceWorker {
pub fn initialize(opt: ServiceOptions) -> io::Result<()> {
let output = match opt.output { FileOptions::File(path) => File::create(path)? };
let sw = ServiceWorker {
output,
input: io::stdin()
};
SERVICE.with(|service| service.replace(Some(sw)));
Ok(())
}
pub fn set_message_handler(new_handler: Box<dyn Handler>) {
HANDLER.with(|handler| handler.replace(Some(new_handler)));
}
pub fn on_message() -> io::Result<usize> {
let mut buf: [u8; 1000] = [0; 1000];
let len =
SERVICE.with(|service| {
if let Some(sw) = &mut *service.borrow_mut() {
sw.input.read(&mut buf)
} else {
Err(io::Error::new(io::ErrorKind::ConnectionRefused, "Cannot borrow service mutably"))
}
})?;
HANDLER.with(|handler| {
if let Some(handler) = &*handler.borrow() {
handler.on_message(&buf[0..len])?;
Ok(len)
} else {
Err(io::Error::new(io::ErrorKind::NotConnected, "Worker was not initialized"))
}
})
}
pub fn post_message(msg: &[u8]) -> std::io::Result<()> {
SERVICE.with(|service| {
if let Some(sw) = &mut *service.borrow_mut() {
sw.output.write_all(msg)
} else {
Err(io::Error::new(io::ErrorKind::NotConnected, "Service was not initialized"))
}
})
}
}