1use alloc::string::String;
2
3use file_system::{FileIdentifier, Mode, Path, Size, UniqueFileIdentifier};
4use futures::block_on;
5use task::TaskIdentifier;
6use virtual_file_system::VirtualFileSystem;
7
8use crate::Result;
9
10pub struct Standard {
11 standard_in: UniqueFileIdentifier,
12 standard_out: UniqueFileIdentifier,
13 standard_error: UniqueFileIdentifier,
14 task: TaskIdentifier,
15 virtual_file_system: &'static VirtualFileSystem<'static>,
16}
17
18impl Drop for Standard {
19 fn drop(&mut self) {
20 let _ = block_on(self.virtual_file_system.close(self.standard_in, self.task));
21
22 let _ = block_on(self.virtual_file_system.close(self.standard_out, self.task));
23
24 let _ = block_on(
25 self.virtual_file_system
26 .close(self.standard_error, self.task),
27 );
28 }
29}
30
31impl Standard {
32 pub async fn open(
33 standard_in: &impl AsRef<Path>,
34 standard_out: &impl AsRef<Path>,
35 standard_error: &impl AsRef<Path>,
36 task: TaskIdentifier,
37 virtual_file_system: &'static VirtualFileSystem<'static>,
38 ) -> Result<Self> {
39 let standard_in = virtual_file_system
40 .open(standard_in, Mode::READ_ONLY.into(), task)
41 .await?;
42
43 let standard_out = virtual_file_system
44 .open(standard_out, Mode::WRITE_ONLY.into(), task)
45 .await?;
46
47 let standard_error = virtual_file_system
48 .open(standard_error, Mode::WRITE_ONLY.into(), task)
49 .await?;
50
51 Ok(Self::new(
52 standard_in,
53 standard_out,
54 standard_error,
55 task,
56 virtual_file_system,
57 ))
58 }
59
60 pub fn new(
61 standard_in: UniqueFileIdentifier,
62 standard_out: UniqueFileIdentifier,
63 standard_error: UniqueFileIdentifier,
64 task: TaskIdentifier,
65 virtual_file_system: &'static VirtualFileSystem,
66 ) -> Self {
67 Self {
68 standard_in,
69 standard_out,
70 standard_error,
71 task,
72 virtual_file_system,
73 }
74 }
75
76 pub async fn print(&self, arguments: &str) {
77 let _ = self
78 .virtual_file_system
79 .write(self.standard_out, arguments.as_bytes(), self.task)
80 .await;
81 }
82
83 pub async fn out_flush(&self) {
84 self.virtual_file_system
85 .flush(self.standard_out, self.task)
86 .await
87 .unwrap();
88 }
89
90 pub async fn write(&self, data: &[u8]) -> Size {
91 match self
92 .virtual_file_system
93 .write(self.standard_out, data, self.task)
94 .await
95 {
96 Ok(size) => size,
97 Err(_) => 0_usize.into(),
98 }
99 }
100
101 pub async fn print_line(&self, arguments: &str) {
102 self.print(arguments).await;
103 self.print("\n").await;
104 }
105
106 pub async fn print_error(&self, arguments: &str) {
107 let _ = self
108 .virtual_file_system
109 .write(self.standard_error, arguments.as_bytes(), self.task)
110 .await;
111 }
112
113 pub async fn print_error_line(&self, arguments: &str) {
114 self.print_error(arguments).await;
115 self.print_error("\n").await;
116 }
117
118 pub async fn read_line(&self, buffer: &mut String) {
119 buffer.clear();
120
121 let _ = self
122 .virtual_file_system
123 .read_line(self.standard_in, self.task, buffer)
124 .await;
125 }
126
127 pub fn get_task(&self) -> TaskIdentifier {
128 self.task
129 }
130
131 pub async fn duplicate(&self) -> Result<Self> {
132 let standard_in = self
133 .virtual_file_system
134 .duplicate_file_identifier(self.standard_in, self.task)
135 .await?;
136
137 let standard_out = self
138 .virtual_file_system
139 .duplicate_file_identifier(self.standard_out, self.task)
140 .await?;
141
142 let standard_error = self
143 .virtual_file_system
144 .duplicate_file_identifier(self.standard_error, self.task)
145 .await?;
146
147 Ok(Self::new(
148 standard_in,
149 standard_out,
150 standard_error,
151 self.task,
152 self.virtual_file_system,
153 ))
154 }
155
156 pub fn split(
157 &self,
158 ) -> (
159 UniqueFileIdentifier,
160 UniqueFileIdentifier,
161 UniqueFileIdentifier,
162 ) {
163 (self.standard_in, self.standard_out, self.standard_error)
164 }
165
166 pub(crate) async fn transfert(mut self, task: TaskIdentifier) -> Result<Self> {
167 self.standard_in = self
168 .virtual_file_system
169 .transfert(
170 self.standard_in,
171 self.task,
172 task,
173 Some(FileIdentifier::STANDARD_IN),
174 )
175 .await?;
176
177 self.standard_out = self
178 .virtual_file_system
179 .transfert(
180 self.standard_out,
181 self.task,
182 task,
183 Some(FileIdentifier::STANDARD_OUT),
184 )
185 .await?;
186
187 self.standard_error = self
188 .virtual_file_system
189 .transfert(
190 self.standard_error,
191 self.task,
192 task,
193 Some(FileIdentifier::STANDARD_ERROR),
194 )
195 .await?;
196
197 self.task = task;
198
199 Ok(self)
200 }
201}