1use alloc::string::String;
2use core::time::Duration;
3use file_system::{AccessFlags, Path};
4use task::TaskIdentifier;
5use virtual_file_system::{File, VirtualFileSystem};
6
7use crate::Result;
8
9pub struct Standard {
10 pub standard_in: File,
11 pub standard_out: File,
12 pub standard_error: File,
13}
14
15impl Standard {
16 pub async fn open(
17 standard_in: &impl AsRef<Path>,
18 standard_out: &impl AsRef<Path>,
19 standard_error: &impl AsRef<Path>,
20 task: TaskIdentifier,
21 virtual_file_system: &'static VirtualFileSystem,
22 ) -> Result<Self> {
23 let standard_in = virtual_file_system
24 .open(standard_in, AccessFlags::Read.into(), task)
25 .await?;
26
27 let standard_out = virtual_file_system
28 .open(standard_out, AccessFlags::Write.into(), task)
29 .await?;
30
31 let standard_error = virtual_file_system
32 .open(standard_error, AccessFlags::Write.into(), task)
33 .await?;
34
35 Ok(Self::new(standard_in, standard_out, standard_error))
36 }
37
38 pub fn new(standard_in: File, standard_out: File, standard_error: File) -> Self {
39 Self {
40 standard_in,
41 standard_out,
42 standard_error,
43 }
44 }
45
46 pub fn input(&mut self) -> &mut File {
47 &mut self.standard_in
48 }
49
50 pub fn out(&mut self) -> &mut File {
51 &mut self.standard_out
52 }
53
54 pub fn error(&mut self) -> &mut File {
55 &mut self.standard_error
56 }
57
58 pub async fn read_line(&mut self, buffer: &mut String) -> virtual_file_system::Result<()> {
59 buffer.clear();
60
61 let mut temp_buffer = [0u8; 1];
65
66 loop {
67 let bytes_read = self.standard_in.read(&mut temp_buffer).await?;
68
69 if bytes_read == 0 {
70 task::sleep(Duration::from_millis(10)).await;
71 continue;
72 }
73
74 if temp_buffer[0] == b'\n' {
75 break;
76 } else {
77 buffer.push(temp_buffer[0] as char);
78 }
79 }
80
81 Ok(())
82 }
83
84 pub async fn duplicate(&self) -> virtual_file_system::Result<Self> {
85 Ok(Self {
86 standard_in: self.standard_in.duplicate().await?,
87 standard_out: self.standard_out.duplicate().await?,
88 standard_error: self.standard_error.duplicate().await?,
89 })
90 }
91
92 pub fn split(self) -> (File, File, File) {
93 (self.standard_in, self.standard_out, self.standard_error)
94 }
95
96 pub async fn close(
97 self,
98 virtual_file_system: &VirtualFileSystem,
99 ) -> virtual_file_system::Result<()> {
100 self.standard_in.close(virtual_file_system).await?;
101 self.standard_out.close(virtual_file_system).await?;
102 self.standard_error.close(virtual_file_system).await?;
103
104 Ok(())
105 }
106}