##// 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 use std::io;
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 /// The kind of user interface error
10 /// The kind of user interface error
7 pub enum UiError {
11 pub enum UiError {
@@ -14,20 +18,31 b' pub enum UiError {'
14 /// The commandline user interface
18 /// The commandline user interface
15 impl Ui {
19 impl Ui {
16 pub fn new() -> Self {
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 /// Write bytes to stdout
33 /// Write bytes to stdout
21 pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> {
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 self.write_stream(&mut stdout, bytes)
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 self.write_stderr(
46 self.write_stderr(
32 &[b"abort: ", error.to_string().as_bytes(), b"\n"].concat(),
47 &[b"abort: ", error.to_string().as_bytes(), b"\n"].concat(),
33 )?;
48 )?;
@@ -36,7 +51,7 b' impl Ui {'
36
51
37 /// Write bytes to stderr
52 /// Write bytes to stderr
38 pub fn write_stderr(&self, bytes: &[u8]) -> Result<(), UiError> {
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 self.write_stream(&mut stderr, bytes)
56 self.write_stream(&mut stderr, bytes)
42 .or_else(|e| Err(UiError::StderrError(e)))?;
57 .or_else(|e| Err(UiError::StderrError(e)))?;
@@ -52,3 +67,43 b' impl Ui {'
52 stream.write_all(bytes)
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