@@ -6,43 +6,49 @@ use crate::ptr::NonNull;
66
77const MAX_BUFFER_SIZE : usize = 8192 ;
88
9- pub struct Stdin ;
9+ pub struct Stdin {
10+ pending : Option < char > ,
11+ }
12+
1013pub struct Stdout ;
1114pub struct Stderr ;
1215
1316impl Stdin {
1417 pub const fn new ( ) -> Stdin {
15- Stdin
18+ Stdin { pending : None }
1619 }
1720}
1821
1922impl io:: Read for Stdin {
20- fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
23+ fn read ( & mut self , mut buf : & mut [ u8 ] ) -> io:: Result < usize > {
2124 let st: NonNull < r_efi:: efi:: SystemTable > = uefi:: env:: system_table ( ) . cast ( ) ;
2225 let stdin = unsafe { ( * st. as_ptr ( ) ) . con_in } ;
2326
24- // Try reading any pending data
25- let inp = match read_key_stroke ( stdin) {
26- Ok ( x) => x,
27- Err ( e) if e == r_efi:: efi:: Status :: NOT_READY => {
28- // Wait for keypress for new data
29- wait_stdin ( stdin) ?;
30- read_key_stroke ( stdin) . map_err ( |x| io:: Error :: from_raw_os_error ( x. as_usize ( ) ) ) ?
27+ // Write any pending character
28+ if let Some ( ch) = self . pending {
29+ if ch. len_utf8 ( ) > buf. len ( ) {
30+ return Ok ( 0 ) ;
3131 }
32- Err ( e) => {
33- return Err ( io:: Error :: from_raw_os_error ( e. as_usize ( ) ) ) ;
34- }
35- } ;
32+ ch. encode_utf8 ( buf) ;
33+ buf = & mut buf[ ch. len_utf8 ( ) ..] ;
34+ self . pending = None ;
35+ }
36+
37+ // Try reading any pending data
38+ let inp = read ( stdin) ?;
3639
3740 // Check if the key is printiable character
38- if inp. scan_code ! = 0x00 {
41+ if inp = = 0x00 {
3942 return Err ( io:: const_io_error!( io:: ErrorKind :: Interrupted , "Special Key Press" ) ) ;
4043 }
4144
42- // SAFETY: Iterator will have only 1 character since we are reading only 1 Key
43- // SAFETY: This character will always be UCS-2 and thus no surrogates.
44- let ch: char = char:: decode_utf16 ( [ inp. unicode_char ] ) . next ( ) . unwrap ( ) . unwrap ( ) ;
45+ // The option unwrap is safe since iterator will have 1 element.
46+ let ch: char = char:: decode_utf16 ( [ inp] )
47+ . next ( )
48+ . unwrap ( )
49+ . map_err ( |_| io:: const_io_error!( io:: ErrorKind :: InvalidInput , "Invalid Input" ) ) ?;
4550 if ch. len_utf8 ( ) > buf. len ( ) {
51+ self . pending = Some ( ch) ;
4652 return Ok ( 0 ) ;
4753 }
4854
@@ -93,8 +99,8 @@ impl io::Write for Stderr {
9399// UCS-2 character should occupy 3 bytes at most in UTF-8
94100pub const STDIN_BUF_SIZE : usize = 3 ;
95101
96- pub fn is_ebadf ( _err : & io:: Error ) -> bool {
97- true
102+ pub fn is_ebadf ( err : & io:: Error ) -> bool {
103+ err . raw_os_error ( ) == Some ( r_efi :: efi :: Status :: UNSUPPORTED . as_usize ( ) )
98104}
99105
100106pub fn panic_output ( ) -> Option < impl io:: Write > {
@@ -132,6 +138,16 @@ unsafe fn simple_text_output(
132138 if res. is_error ( ) { Err ( io:: Error :: from_raw_os_error ( res. as_usize ( ) ) ) } else { Ok ( ( ) ) }
133139}
134140
141+ fn read ( stdin : * mut r_efi:: protocols:: simple_text_input:: Protocol ) -> io:: Result < u16 > {
142+ loop {
143+ match read_key_stroke ( stdin) {
144+ Ok ( x) => return Ok ( x. unicode_char ) ,
145+ Err ( e) if e == r_efi:: efi:: Status :: NOT_READY => wait_stdin ( stdin) ?,
146+ Err ( e) => return Err ( io:: Error :: from_raw_os_error ( e. as_usize ( ) ) ) ,
147+ }
148+ }
149+ }
150+
135151fn wait_stdin ( stdin : * mut r_efi:: protocols:: simple_text_input:: Protocol ) -> io:: Result < ( ) > {
136152 let boot_services: NonNull < r_efi:: efi:: BootServices > =
137153 uefi:: env:: boot_services ( ) . unwrap ( ) . cast ( ) ;
0 commit comments