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