Newer
Older
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
use crate::formatting::El;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::sync::mpsc::{RecvError, Sender, TryRecvError};
use std::thread::{sleep, JoinHandle};
use std::time::Duration;
use std::{io, thread};
type ThreadWriterResult = Result<(), ThreadWriterError>;
pub struct ThreadWriter {
handle: JoinHandle<ThreadWriterResult>,
}
impl ThreadWriter {
pub fn join(self) -> thread::Result<ThreadWriterResult> {
self.handle.join()
}
}
#[derive(thiserror::Error, Debug)]
pub enum ThreadWriterError {
#[error("There was an issue reading the incoming element: {0}")]
IncomingError(#[from] RecvError),
#[error("There was an issue opening the target file: {0}")]
OpenFileError(io::Error),
#[error("There was an issue writing to the target file: {0}")]
WriteFileError(io::Error),
}
fn write_error(e: io::Error) -> ThreadWriterError {
ThreadWriterError::WriteFileError(e)
}
pub fn create_output_canvas<T: AsRef<Path> + Send + 'static>(
width: usize,
height: usize,
path: T,
) -> (Sender<String>, ThreadWriter) {
let (send, receiver) = std::sync::mpsc::channel::<String>();
let handle = thread::spawn(move || {
let mut file = File::create(path).map_err(write_error)?;
let container_attrs = vec![
("width", format!("{}", width)).into(),
("height", format!("{}", height)).into(),
("viewport", format!("0 0 {} {}", width, height)).into(),
];
file.write_all(El::open("svg", &container_attrs).as_bytes())
.map_err(write_error)?;
file.write_all("\n".as_bytes()).map_err(write_error)?;
loop {
match receiver.try_recv() {
Ok(value) => {
file.write_all(value.as_bytes()).map_err(write_error)?;
file.write_all("\n".as_bytes()).map_err(write_error)?;
}
Err(TryRecvError::Empty) => sleep(Duration::from_millis(5)),
Err(TryRecvError::Disconnected) => break,
}
}
file.write_all(El::close("svg").as_bytes())
.map_err(write_error)?;
Ok(())
});
(send, ThreadWriter { handle })
}