executable/
standard.rs

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        // This function read_until the source until the delimiter '\n' is found.
62        // If the delimiter is not found, expand the buffer
63
64        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}