executable/
standard.rs

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}