1use alloc::boxed::Box;
2use core::future;
3use core::mem::MaybeUninit;
4use core::task::Poll;
5
6use async_trait::async_trait;
7use uhyve_interface::parameters::WriteParams;
8use uhyve_interface::{GuestVirtAddr, Hypercall};
9use zerocopy::IntoBytes;
10
11use crate::console::CONSOLE;
12use crate::fd::{ObjectInterface, PollEvent, STDERR_FILENO, STDOUT_FILENO};
13use crate::io;
14use crate::syscalls::interfaces::uhyve_hypercall;
15
16#[derive(Debug)]
17pub struct GenericStdin;
18
19#[async_trait]
20impl ObjectInterface for GenericStdin {
21 async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
22 let available = if CONSOLE.lock().is_empty() {
23 PollEvent::empty()
24 } else {
25 PollEvent::POLLIN | PollEvent::POLLRDNORM | PollEvent::POLLRDBAND
26 };
27
28 Ok(event & available)
29 }
30
31 async fn read(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
32 future::poll_fn(|cx| {
33 let mut read_bytes = 0;
34 let mut guard = CONSOLE.lock();
35
36 while let Some(byte) = guard.read() {
37 let c = unsafe { char::from_u32_unchecked(byte.into()) };
38 guard.write(c.as_bytes());
39
40 buf[read_bytes].write(byte);
41 read_bytes += 1;
42
43 if read_bytes >= buf.len() {
44 return Poll::Ready(Ok(read_bytes));
45 }
46 }
47
48 if read_bytes > 0 {
49 Poll::Ready(Ok(read_bytes))
50 } else {
51 guard.register_waker(cx.waker());
52 Poll::Pending
53 }
54 })
55 .await
56 }
57
58 async fn isatty(&self) -> io::Result<bool> {
59 Ok(true)
60 }
61}
62
63impl GenericStdin {
64 pub const fn new() -> Self {
65 Self {}
66 }
67}
68
69#[derive(Debug)]
70pub struct GenericStdout;
71
72#[async_trait]
73impl ObjectInterface for GenericStdout {
74 async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
75 let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
76 Ok(event & available)
77 }
78
79 async fn write(&self, buf: &[u8]) -> io::Result<usize> {
80 CONSOLE.lock().write(buf);
81 Ok(buf.len())
82 }
83
84 async fn isatty(&self) -> io::Result<bool> {
85 Ok(true)
86 }
87}
88
89impl GenericStdout {
90 pub const fn new() -> Self {
91 Self {}
92 }
93}
94
95#[derive(Debug)]
96pub struct GenericStderr;
97
98#[async_trait]
99impl ObjectInterface for GenericStderr {
100 async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
101 let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
102 Ok(event & available)
103 }
104
105 async fn write(&self, buf: &[u8]) -> io::Result<usize> {
106 CONSOLE.lock().write(buf);
107 Ok(buf.len())
108 }
109
110 async fn isatty(&self) -> io::Result<bool> {
111 Ok(true)
112 }
113}
114
115impl GenericStderr {
116 pub const fn new() -> Self {
117 Self {}
118 }
119}
120
121#[derive(Debug)]
122pub struct UhyveStdin;
123
124#[async_trait]
125impl ObjectInterface for UhyveStdin {
126 async fn isatty(&self) -> io::Result<bool> {
127 Ok(true)
128 }
129}
130
131impl UhyveStdin {
132 pub const fn new() -> Self {
133 Self {}
134 }
135}
136
137#[derive(Debug)]
138pub struct UhyveStdout;
139
140#[async_trait]
141impl ObjectInterface for UhyveStdout {
142 async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
143 let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
144 Ok(event & available)
145 }
146
147 async fn write(&self, buf: &[u8]) -> io::Result<usize> {
148 let write_params = WriteParams {
149 fd: STDOUT_FILENO,
150 buf: GuestVirtAddr::new(buf.as_ptr() as u64),
151 len: buf.len(),
152 };
153 uhyve_hypercall(Hypercall::FileWrite(&write_params));
154
155 Ok(write_params.len)
156 }
157
158 async fn isatty(&self) -> io::Result<bool> {
159 Ok(true)
160 }
161}
162
163impl UhyveStdout {
164 pub const fn new() -> Self {
165 Self {}
166 }
167}
168
169#[derive(Debug)]
170pub struct UhyveStderr;
171
172#[async_trait]
173impl ObjectInterface for UhyveStderr {
174 async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
175 let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
176 Ok(event & available)
177 }
178
179 async fn write(&self, buf: &[u8]) -> io::Result<usize> {
180 let write_params = WriteParams {
181 fd: STDERR_FILENO,
182 buf: GuestVirtAddr::new(buf.as_ptr() as u64),
183 len: buf.len(),
184 };
185 uhyve_hypercall(Hypercall::FileWrite(&write_params));
186
187 Ok(write_params.len)
188 }
189
190 async fn isatty(&self) -> io::Result<bool> {
191 Ok(true)
192 }
193}
194
195impl UhyveStderr {
196 pub const fn new() -> Self {
197 Self {}
198 }
199}