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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use std::io::{Result, Write};
use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::thread;
mod os;
enum Op {
Write(Vec<u8>),
Clear,
Flush,
Close,
}
pub struct Printer {
writes: Arc<Mutex<Sender<Op>>>,
}
impl Printer {
pub fn new<W>(mut underlying: W, interval: Duration) -> Printer
where W: Write + Send + 'static
{
let (writer, writes) = channel();
let writers = Arc::new(Mutex::new(writer));
let sleeper = writers.clone();
let forwards = writers.clone();
let printer = Printer { writes: forwards };
let (closer, closing) = channel();
thread::spawn(move || {
loop {
if let Ok(_) = closing.try_recv() {
return;
}
thread::sleep(interval);
if let Ok(s) = sleeper.lock() {
let _ = s.send(Op::Flush);
}
}
});
thread::spawn(move || {
let mut buffer = vec![];
let mut lines = 0;
loop {
if let Ok(op) = writes.recv() {
match op {
Op::Clear => {
buffer.clear();
lines = 0
}
Op::Close => {
let _ = closer.send(());
return;
}
Op::Flush => {
if buffer.is_empty() {
continue;
}
for _ in 0..lines {
os::clear_line_move_one_up(&mut underlying);
}
lines = buffer.iter().filter(|&b| *b == b'\n').count();
let _ = underlying.write(&buffer);
let _ = underlying.flush();
buffer.clear();
}
Op::Write(data) => buffer.extend(data),
}
}
}
});
printer
}
pub fn clear(&self) {
let _ = self.writes.lock().unwrap().send(Op::Clear);
}
pub fn close(&self) {
let _ = self.writes.lock().unwrap().send(Op::Close);
}
}
impl Write for Printer {
fn write(&mut self, data: &[u8]) -> Result<usize> {
let _ = self.writes.lock().unwrap().send(Op::Write(data.to_owned()));
Ok(data.len())
}
fn flush(&mut self) -> Result<()> {
let _ = self.writes.lock().unwrap().send(Op::Flush);
Ok(())
}
}
impl Drop for Printer {
fn drop(&mut self) {
self.close();
}
}
#[test]
fn it_works() {}