Skip to content

Commit 3c9cae1

Browse files
committed
Fixes from PR
- is_ebadf always returns false - Allow reading partial characters to buffer Signed-off-by: Ayush Singh <[email protected]>
1 parent a9a5ef9 commit 3c9cae1

File tree

1 file changed

+45
-25
lines changed

1 file changed

+45
-25
lines changed

library/std/src/sys/uefi/stdio.rs

+45-25
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,71 @@ use crate::os::uefi;
55
use crate::ptr::NonNull;
66

77
pub struct Stdin {
8-
pending: Option<char>,
8+
pending: [Option<u8>; 2],
99
}
1010

1111
pub struct Stdout;
1212
pub struct Stderr;
1313

1414
impl Stdin {
1515
pub const fn new() -> Stdin {
16-
Stdin { pending: None }
16+
Stdin { pending: [None; 2] }
1717
}
1818
}
1919

2020
impl io::Read for Stdin {
21-
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
21+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
22+
if buf.is_empty() {
23+
return Ok(0);
24+
}
25+
2226
let st: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
2327
let stdin = unsafe { (*st.as_ptr()).con_in };
28+
let mut count: usize = 0;
2429

2530
// Write any pending character
26-
if let Some(ch) = self.pending {
27-
if ch.len_utf8() > buf.len() {
28-
return Ok(0);
31+
while let Some(byte) = self.pending[0] {
32+
buf[count] = byte;
33+
count += 1;
34+
self.pending[0] = self.pending[1].take();
35+
36+
if count >= buf.len() {
37+
return Ok(count);
2938
}
30-
ch.encode_utf8(buf);
31-
buf = &mut buf[ch.len_utf8()..];
32-
self.pending = None;
3339
}
3440

35-
// Try reading any pending data
36-
let inp = read(stdin)?;
37-
38-
// Check if the key is printiable character
41+
// Try reading new character
42+
let inp = simple_text_input_read(stdin)?;
3943
if inp == 0x00 {
4044
return Err(io::const_io_error!(io::ErrorKind::Interrupted, "Special Key Press"));
4145
}
4246

43-
// The option unwrap is safe since iterator will have 1 element.
44-
let ch: char = char::decode_utf16([inp])
45-
.next()
46-
.unwrap()
47-
.map_err(|_| io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Input"))?;
48-
if ch.len_utf8() > buf.len() {
49-
self.pending = Some(ch);
50-
return Ok(0);
47+
let Some(Ok(ch)) = char::decode_utf16([inp]).next() else {
48+
return Err(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Input"));
49+
};
50+
51+
// This will always be > 0
52+
let buf_free_count = buf.len() - count;
53+
assert!(buf_free_count > 0);
54+
55+
if ch.len_utf8() > buf_free_count {
56+
let mut temp = [0u8; 3];
57+
ch.encode_utf8(&mut temp);
58+
59+
buf[count..].copy_from_slice(&temp[..buf_free_count]);
60+
count += buf_free_count;
61+
62+
for (i, v) in temp[buf_free_count..].into_iter().enumerate() {
63+
self.pending[i] = Some(*v);
64+
}
65+
66+
return Ok(count);
5167
}
5268

5369
ch.encode_utf8(buf);
70+
count += ch.len_utf8();
5471

55-
Ok(ch.len_utf8())
72+
Ok(count)
5673
}
5774
}
5875

@@ -97,8 +114,8 @@ impl io::Write for Stderr {
97114
// UCS-2 character should occupy 3 bytes at most in UTF-8
98115
pub const STDIN_BUF_SIZE: usize = 3;
99116

100-
pub fn is_ebadf(err: &io::Error) -> bool {
101-
err.raw_os_error() == Some(r_efi::efi::Status::UNSUPPORTED.as_usize())
117+
pub fn is_ebadf(_err: &io::Error) -> bool {
118+
false
102119
}
103120

104121
pub fn panic_output() -> Option<impl io::Write> {
@@ -116,6 +133,7 @@ fn write(
116133
};
117134

118135
let mut utf16: Vec<u16> = utf8.encode_utf16().collect();
136+
// NULL terminate the string
119137
utf16.push(0);
120138

121139
unsafe { simple_text_output(protocol, &mut utf16) }?;
@@ -131,7 +149,9 @@ unsafe fn simple_text_output(
131149
if res.is_error() { Err(io::Error::from_raw_os_error(res.as_usize())) } else { Ok(()) }
132150
}
133151

134-
fn read(stdin: *mut r_efi::protocols::simple_text_input::Protocol) -> io::Result<u16> {
152+
fn simple_text_input_read(
153+
stdin: *mut r_efi::protocols::simple_text_input::Protocol,
154+
) -> io::Result<u16> {
135155
loop {
136156
match read_key_stroke(stdin) {
137157
Ok(x) => return Ok(x.unicode_char),

0 commit comments

Comments
 (0)