##// END OF EJS Templates
rhg: add buffered stdout writing possibility...
Antoine Cezar -
r45921:eb55274d default
parent child Browse files
Show More
@@ -1,7 +1,11 b''
1 1 use std::io;
2 use std::io::Write;
2 use std::io::{ErrorKind, Write};
3 3
4 pub struct Ui {}
4 #[derive(Debug)]
5 pub struct Ui {
6 stdout: std::io::Stdout,
7 stderr: std::io::Stderr,
8 }
5 9
6 10 /// The kind of user interface error
7 11 pub enum UiError {
@@ -14,20 +18,31 b' pub enum UiError {'
14 18 /// The commandline user interface
15 19 impl Ui {
16 20 pub fn new() -> Self {
17 Ui {}
21 Ui {
22 stdout: std::io::stdout(),
23 stderr: std::io::stderr(),
24 }
25 }
26
27 /// Returns a buffered handle on stdout for faster batch printing
28 /// operations.
29 pub fn stdout_buffer(&self) -> StdoutBuffer<std::io::StdoutLock> {
30 StdoutBuffer::new(self.stdout.lock())
18 31 }
19 32
20 33 /// Write bytes to stdout
21 34 pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> {
22 let mut stdout = io::stdout();
35 let mut stdout = self.stdout.lock();
23 36
24 37 self.write_stream(&mut stdout, bytes)
25 .or_else(|e| self.into_stdout_error(e))?;
38 .or_else(|e| self.handle_stdout_error(e))?;
26 39
27 stdout.flush().or_else(|e| self.into_stdout_error(e))
40 stdout.flush().or_else(|e| self.handle_stdout_error(e))
28 41 }
29 42
30 fn into_stdout_error(&self, error: io::Error) -> Result<(), UiError> {
43 /// Sometimes writing to stdout is not possible, try writing to stderr to
44 /// signal that failure, otherwise just bail.
45 fn handle_stdout_error(&self, error: io::Error) -> Result<(), UiError> {
31 46 self.write_stderr(
32 47 &[b"abort: ", error.to_string().as_bytes(), b"\n"].concat(),
33 48 )?;
@@ -36,7 +51,7 b' impl Ui {'
36 51
37 52 /// Write bytes to stderr
38 53 pub fn write_stderr(&self, bytes: &[u8]) -> Result<(), UiError> {
39 let mut stderr = io::stderr();
54 let mut stderr = self.stderr.lock();
40 55
41 56 self.write_stream(&mut stderr, bytes)
42 57 .or_else(|e| Err(UiError::StderrError(e)))?;
@@ -52,3 +67,43 b' impl Ui {'
52 67 stream.write_all(bytes)
53 68 }
54 69 }
70
71 /// A buffered stdout writer for faster batch printing operations.
72 pub struct StdoutBuffer<W: Write> {
73 buf: io::BufWriter<W>,
74 }
75
76 impl<W: Write> StdoutBuffer<W> {
77 pub fn new(writer: W) -> Self {
78 let buf = io::BufWriter::new(writer);
79 Self { buf }
80 }
81
82 /// Write bytes to stdout buffer
83 pub fn write_all(&mut self, bytes: &[u8]) -> Result<(), UiError> {
84 self.buf.write_all(bytes).or_else(|e| self.io_err(e))
85 }
86
87 /// Flush bytes to stdout
88 pub fn flush(&mut self) -> Result<(), UiError> {
89 self.buf.flush().or_else(|e| self.io_err(e))
90 }
91
92 fn io_err(&self, error: io::Error) -> Result<(), UiError> {
93 if let ErrorKind::BrokenPipe = error.kind() {
94 // This makes `| head` work for example
95 return Ok(());
96 }
97 let mut stderr = io::stderr();
98
99 stderr
100 .write_all(
101 &[b"abort: ", error.to_string().as_bytes(), b"\n"].concat(),
102 )
103 .map_err(|e| UiError::StderrError(e))?;
104
105 stderr.flush().map_err(|e| UiError::StderrError(e))?;
106
107 Err(UiError::StdoutError(error))
108 }
109 }
General Comments 0
You need to be logged in to leave comments. Login now