1use crate::{FileDescriptor, FsError, Result, VirtualFile};
5use std::io::{self, Read, Seek, Write};
6
7macro_rules! impl_virtualfile_on_std_streams {
8 ($name:ident { readable: $readable:expr, writable: $writable:expr $(,)* }) => {
9 #[derive(Debug, Default)]
12 pub struct $name {
13 pub buf: Vec<u8>,
14 }
15
16 impl $name {
17 const fn is_readable(&self) -> bool {
18 $readable
19 }
20
21 const fn is_writable(&self) -> bool {
22 $writable
23 }
24 }
25
26 impl VirtualFile for $name {
27 fn last_accessed(&self) -> u64 {
28 0
29 }
30
31 fn last_modified(&self) -> u64 {
32 0
33 }
34
35 fn created_time(&self) -> u64 {
36 0
37 }
38
39 fn size(&self) -> u64 {
40 0
41 }
42
43 fn set_len(&mut self, _new_size: u64) -> Result<()> {
44 Err(FsError::PermissionDenied)
45 }
46
47 fn unlink(&mut self) -> Result<()> {
48 Ok(())
49 }
50
51 fn bytes_available(&self) -> Result<usize> {
52 unimplemented!();
53 }
54
55 fn get_fd(&self) -> Option<FileDescriptor> {
56 None
57 }
58 }
59
60 impl_virtualfile_on_std_streams!(impl Seek for $name);
61 impl_virtualfile_on_std_streams!(impl Read for $name);
62 impl_virtualfile_on_std_streams!(impl Write for $name);
63 };
64
65 (impl Seek for $name:ident) => {
66 impl Seek for $name {
67 fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
68 Err(io::Error::new(
69 io::ErrorKind::PermissionDenied,
70 concat!("cannot seek `", stringify!($name), "`"),
71 ))
72 }
73 }
74 };
75
76 (impl Read for $name:ident) => {
77 impl Read for $name {
78 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
79 if self.is_readable() {
80 let length = self.buf.as_slice().read(buf)?;
81
82 self.buf.drain(..length);
84
85 Ok(length)
86 } else {
87 Err(io::Error::new(
88 io::ErrorKind::PermissionDenied,
89 concat!("cannot read from `", stringify!($name), "`"),
90 ))
91 }
92 }
93
94 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
95 if self.is_readable() {
96 let length = self.buf.as_slice().read_to_end(buf)?;
97
98 self.buf.clear();
100
101 Ok(length)
102 } else {
103 Err(io::Error::new(
104 io::ErrorKind::PermissionDenied,
105 concat!("cannot read from `", stringify!($name), "`"),
106 ))
107 }
108 }
109
110 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
111 if self.is_readable() {
112 let length = self.buf.as_slice().read_to_string(buf)?;
113
114 self.buf.drain(..length);
116
117 Ok(length)
118 } else {
119 Err(io::Error::new(
120 io::ErrorKind::PermissionDenied,
121 concat!("cannot read from `", stringify!($name), "`"),
122 ))
123 }
124 }
125
126 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
127 if self.is_readable() {
128 self.buf.as_slice().read_exact(buf)?;
129
130 self.buf.drain(..buf.len());
131
132 Ok(())
133 } else {
134 Err(io::Error::new(
135 io::ErrorKind::PermissionDenied,
136 concat!("cannot read from `", stringify!($name), "`"),
137 ))
138 }
139 }
140 }
141 };
142
143 (impl Write for $name:ident) => {
144 impl Write for $name {
145 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
146 if self.is_writable() {
147 self.buf.write(buf)
148 } else {
149 Err(io::Error::new(
150 io::ErrorKind::PermissionDenied,
151 concat!("cannot write to `", stringify!($name), "`"),
152 ))
153 }
154 }
155
156 fn flush(&mut self) -> io::Result<()> {
157 if self.is_writable() {
158 self.buf.flush()
159 } else {
160 Err(io::Error::new(
161 io::ErrorKind::PermissionDenied,
162 concat!("cannot flush `", stringify!($name), "`"),
163 ))
164 }
165 }
166
167 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
168 if self.is_writable() {
169 self.buf.write_all(buf)
170 } else {
171 Err(io::Error::new(
172 io::ErrorKind::PermissionDenied,
173 concat!("cannot write to `", stringify!($name), "`"),
174 ))
175 }
176 }
177 }
178 };
179}
180
181impl_virtualfile_on_std_streams!(Stdin {
182 readable: true,
183 writable: false,
184});
185impl_virtualfile_on_std_streams!(Stdout {
186 readable: false,
187 writable: true,
188});
189impl_virtualfile_on_std_streams!(Stderr {
190 readable: false,
191 writable: true,
192});
193
194#[cfg(test)]
195mod test_read_write_seek {
196 use crate::mem_fs::*;
197 use std::io::{self, Read, Seek, Write};
198
199 #[test]
200 fn test_read_stdin() {
201 let mut stdin = Stdin {
202 buf: vec![b'f', b'o', b'o', b'b', b'a', b'r'],
203 };
204 let mut buffer = [0; 3];
205
206 assert!(
207 matches!(stdin.read(&mut buffer), Ok(3)),
208 "reading bytes from `stdin`",
209 );
210 assert_eq!(
211 buffer,
212 [b'f', b'o', b'o'],
213 "checking the bytes read from `stdin`"
214 );
215
216 let mut buffer = Vec::new();
217
218 assert!(
219 matches!(stdin.read_to_end(&mut buffer), Ok(3)),
220 "reading bytes again from `stdin`",
221 );
222 assert_eq!(
223 buffer,
224 &[b'b', b'a', b'r'],
225 "checking the bytes read from `stdin`"
226 );
227
228 let mut buffer = [0; 1];
229
230 assert!(
231 stdin.read_exact(&mut buffer).is_err(),
232 "cannot read bytes again because `stdin` has fully consumed",
233 );
234 }
235
236 #[test]
237 fn test_write_stdin() {
238 let mut stdin = Stdin { buf: vec![] };
239
240 assert!(stdin.write(b"bazqux").is_err(), "cannot write into `stdin`");
241 }
242
243 #[test]
244 fn test_seek_stdin() {
245 let mut stdin = Stdin {
246 buf: vec![b'f', b'o', b'o', b'b', b'a', b'r'],
247 };
248
249 assert!(
250 stdin.seek(io::SeekFrom::End(0)).is_err(),
251 "cannot seek `stdin`",
252 );
253 }
254
255 #[test]
256 fn test_read_stdout() {
257 let mut stdout = Stdout {
258 buf: vec![b'f', b'o', b'o', b'b', b'a', b'r'],
259 };
260 let mut buffer = String::new();
261
262 assert!(
263 stdout.read_to_string(&mut buffer).is_err(),
264 "cannot read from `stdout`"
265 );
266 }
267
268 #[test]
269 fn test_write_stdout() {
270 let mut stdout = Stdout { buf: vec![] };
271
272 assert!(
273 matches!(stdout.write(b"baz"), Ok(3)),
274 "writing into `stdout`",
275 );
276 assert!(
277 matches!(stdout.write(b"qux"), Ok(3)),
278 "writing again into `stdout`",
279 );
280 assert_eq!(
281 stdout.buf,
282 &[b'b', b'a', b'z', b'q', b'u', b'x'],
283 "checking the content of `stdout`",
284 );
285 }
286
287 #[test]
288 fn test_seek_stdout() {
289 let mut stdout = Stdout {
290 buf: vec![b'f', b'o', b'o', b'b', b'a', b'r'],
291 };
292
293 assert!(
294 stdout.seek(io::SeekFrom::End(0)).is_err(),
295 "cannot seek `stdout`",
296 );
297 }
298
299 #[test]
300 fn test_read_stderr() {
301 let mut stderr = Stderr {
302 buf: vec![b'f', b'o', b'o', b'b', b'a', b'r'],
303 };
304 let mut buffer = String::new();
305
306 assert!(
307 stderr.read_to_string(&mut buffer).is_err(),
308 "cannot read from `stderr`"
309 );
310 }
311
312 #[test]
313 fn test_write_stderr() {
314 let mut stderr = Stderr { buf: vec![] };
315
316 assert!(
317 matches!(stderr.write(b"baz"), Ok(3)),
318 "writing into `stderr`",
319 );
320 assert!(
321 matches!(stderr.write(b"qux"), Ok(3)),
322 "writing again into `stderr`",
323 );
324 assert_eq!(
325 stderr.buf,
326 &[b'b', b'a', b'z', b'q', b'u', b'x'],
327 "checking the content of `stderr`",
328 );
329 }
330
331 #[test]
332 fn test_seek_stderr() {
333 let mut stderr = Stderr {
334 buf: vec![b'f', b'o', b'o', b'b', b'a', b'r'],
335 };
336
337 assert!(
338 stderr.seek(io::SeekFrom::End(0)).is_err(),
339 "cannot seek `stderr`",
340 );
341 }
342}