@@ -5,54 +5,71 @@ use crate::os::uefi;
5
5
use crate :: ptr:: NonNull ;
6
6
7
7
pub struct Stdin {
8
- pending : Option < char > ,
8
+ pending : [ Option < u8 > ; 2 ] ,
9
9
}
10
10
11
11
pub struct Stdout ;
12
12
pub struct Stderr ;
13
13
14
14
impl Stdin {
15
15
pub const fn new ( ) -> Stdin {
16
- Stdin { pending : None }
16
+ Stdin { pending : [ None ; 2 ] }
17
17
}
18
18
}
19
19
20
20
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
+
22
26
let st: NonNull < r_efi:: efi:: SystemTable > = uefi:: env:: system_table ( ) . cast ( ) ;
23
27
let stdin = unsafe { ( * st. as_ptr ( ) ) . con_in } ;
28
+ let mut count: usize = 0 ;
24
29
25
30
// 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) ;
29
38
}
30
- ch. encode_utf8 ( buf) ;
31
- buf = & mut buf[ ch. len_utf8 ( ) ..] ;
32
- self . pending = None ;
33
39
}
34
40
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) ?;
39
43
if inp == 0x00 {
40
44
return Err ( io:: const_io_error!( io:: ErrorKind :: Interrupted , "Special Key Press" ) ) ;
41
45
}
42
46
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) ;
51
67
}
52
68
53
69
ch. encode_utf8 ( buf) ;
70
+ count += ch. len_utf8 ( ) ;
54
71
55
- Ok ( ch . len_utf8 ( ) )
72
+ Ok ( count )
56
73
}
57
74
}
58
75
@@ -97,8 +114,8 @@ impl io::Write for Stderr {
97
114
// UCS-2 character should occupy 3 bytes at most in UTF-8
98
115
pub const STDIN_BUF_SIZE : usize = 3 ;
99
116
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
102
119
}
103
120
104
121
pub fn panic_output ( ) -> Option < impl io:: Write > {
@@ -116,6 +133,7 @@ fn write(
116
133
} ;
117
134
118
135
let mut utf16: Vec < u16 > = utf8. encode_utf16 ( ) . collect ( ) ;
136
+ // NULL terminate the string
119
137
utf16. push ( 0 ) ;
120
138
121
139
unsafe { simple_text_output ( protocol, & mut utf16) } ?;
@@ -131,7 +149,9 @@ unsafe fn simple_text_output(
131
149
if res. is_error ( ) { Err ( io:: Error :: from_raw_os_error ( res. as_usize ( ) ) ) } else { Ok ( ( ) ) }
132
150
}
133
151
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 > {
135
155
loop {
136
156
match read_key_stroke ( stdin) {
137
157
Ok ( x) => return Ok ( x. unicode_char ) ,
0 commit comments