layered_io/
layered_writer.rs1use crate::{Bufferable, WriteLayered};
2#[cfg(windows)]
3use io_extras::os::windows::{
4 AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, RawHandleOrSocket,
5};
6use std::fmt::{self, Arguments};
7use std::io::{self, IoSlice, Write};
8#[cfg(not(windows))]
9use {
10 io_extras::os::rustix::{AsRawFd, RawFd},
11 std::os::fd::{AsFd, BorrowedFd},
12};
13
14pub struct LayeredWriter<Inner> {
16 inner: Option<Inner>,
17}
18
19impl<Inner: Write> LayeredWriter<Inner> {
20 pub fn new(inner: Inner) -> Self {
22 Self { inner: Some(inner) }
23 }
24
25 pub fn get_ref(&self) -> &Inner {
27 self.inner
28 .as_ref()
29 .expect("get_ref() called on closed LayeredWriter")
30 }
31
32 pub fn get_mut(&mut self) -> &mut Inner {
36 self.inner
37 .as_mut()
38 .expect("get_mut() called on closed LayeredWriter")
39 }
40
41 pub fn close_into_inner(mut self) -> io::Result<Inner> {
43 match &mut self.inner {
44 Some(_) => {
45 let mut inner = self.inner.take().unwrap();
46 inner.flush()?;
47 Ok(inner)
48 }
49 None => Err(stream_already_ended()),
50 }
51 }
52
53 pub fn abandon_into_inner(mut self) -> Option<Inner> {
55 self.inner.take()
56 }
57}
58
59impl<Inner: Write> WriteLayered for LayeredWriter<Inner> {
60 #[inline]
61 fn close(&mut self) -> io::Result<()> {
62 match &mut self.inner {
63 Some(_) => self.inner.take().unwrap().flush(),
64 None => Err(stream_already_ended()),
65 }
66 }
67}
68
69impl<Inner> Bufferable for LayeredWriter<Inner> {
70 #[inline]
71 fn abandon(&mut self) {
72 self.inner = None;
73 }
74}
75
76impl<Inner: Write> Write for LayeredWriter<Inner> {
77 #[inline]
78 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
79 match &mut self.inner {
80 Some(inner) => inner.write(buf).map_err(|e| {
81 drop(self.inner.take().unwrap());
82 e
83 }),
84 None => Err(stream_already_ended()),
85 }
86 }
87
88 #[inline]
89 fn flush(&mut self) -> io::Result<()> {
90 match &mut self.inner {
91 Some(inner) => inner.flush().map_err(|e| {
92 drop(self.inner.take().unwrap());
93 e
94 }),
95 None => Err(stream_already_ended()),
96 }
97 }
98
99 #[inline]
100 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
101 match &mut self.inner {
102 Some(inner) => inner.write_vectored(bufs).map_err(|e| {
103 drop(self.inner.take().unwrap());
104 e
105 }),
106 None => Err(stream_already_ended()),
107 }
108 }
109
110 #[cfg(can_vector)]
111 #[inline]
112 fn is_write_vectored(&self) -> bool {
113 match &self.inner {
114 Some(inner) => inner.is_write_vectored(),
115 None => false,
116 }
117 }
118
119 #[inline]
120 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
121 match &mut self.inner {
122 Some(inner) => inner.write_all(buf).map_err(|e| {
123 drop(self.inner.take().unwrap());
124 e
125 }),
126 None => Err(stream_already_ended()),
127 }
128 }
129
130 #[cfg(write_all_vectored)]
131 #[inline]
132 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
133 match &mut self.inner {
134 Some(inner) => inner.write_all_vectored(bufs).map_err(|e| {
135 drop(self.inner.take().unwrap());
136 e
137 }),
138 None => Err(stream_already_ended()),
139 }
140 }
141
142 #[inline]
143 fn write_fmt(&mut self, fmt: Arguments<'_>) -> io::Result<()> {
144 match &mut self.inner {
145 Some(inner) => inner.write_fmt(fmt).map_err(|e| {
146 drop(self.inner.take().unwrap());
147 e
148 }),
149 None => Err(stream_already_ended()),
150 }
151 }
152}
153
154#[cfg(feature = "terminal-io")]
155impl<RW: terminal_io::WriteTerminal> terminal_io::Terminal for LayeredWriter<RW> {}
156
157#[cfg(feature = "terminal-io")]
158impl<RW: terminal_io::WriteTerminal> terminal_io::WriteTerminal for LayeredWriter<RW> {
159 #[inline]
160 fn color_support(&self) -> terminal_io::TerminalColorSupport {
161 self.inner.as_ref().unwrap().color_support()
162 }
163
164 #[inline]
165 fn color_preference(&self) -> bool {
166 self.inner.as_ref().unwrap().color_preference()
167 }
168
169 #[inline]
170 fn is_output_terminal(&self) -> bool {
171 self.inner
172 .as_ref()
173 .map(|c| c.is_output_terminal())
174 .unwrap_or(false)
175 }
176}
177
178#[cfg(not(windows))]
179impl<Inner: Write + AsRawFd> AsRawFd for LayeredWriter<Inner> {
180 #[inline]
181 fn as_raw_fd(&self) -> RawFd {
182 match &self.inner {
183 Some(inner) => inner.as_raw_fd(),
184 None => panic!("as_raw_fd() called on closed LayeredWriter"),
185 }
186 }
187}
188
189#[cfg(not(windows))]
190impl<Inner: Write + AsFd> AsFd for LayeredWriter<Inner> {
191 #[inline]
192 fn as_fd(&self) -> BorrowedFd<'_> {
193 match &self.inner {
194 Some(inner) => inner.as_fd(),
195 None => panic!("as_fd() called on closed LayeredWriter"),
196 }
197 }
198}
199
200#[cfg(windows)]
201impl<Inner: Write + AsRawHandleOrSocket> AsRawHandleOrSocket for LayeredWriter<Inner> {
202 #[inline]
203 fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
204 match &self.inner {
205 Some(inner) => inner.as_raw_handle_or_socket(),
206 None => panic!("as_raw_handle_or_socket() called on closed LayeredWriter"),
207 }
208 }
209}
210
211#[cfg(windows)]
212impl<Inner: Write + AsHandleOrSocket> AsHandleOrSocket for LayeredWriter<Inner> {
213 #[inline]
214 fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
215 match &self.inner {
216 Some(inner) => inner.as_handle_or_socket(),
217 None => panic!("as_handle_or_socket() called on closed LayeredWriter"),
218 }
219 }
220}
221
222impl<Inner: fmt::Debug> fmt::Debug for LayeredWriter<Inner> {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 let mut b = f.debug_struct("LayeredWriter");
225 b.field("inner", &self.inner);
226 b.finish()
227 }
228}
229
230fn stream_already_ended() -> io::Error {
231 io::Error::new(io::ErrorKind::BrokenPipe, "stream has already ended")
232}
233
234impl<Inner> Drop for LayeredWriter<Inner> {
235 fn drop(&mut self) {
236 assert!(self.inner.is_none(), "stream was not closed or abandoned");
237 }
238}