@@ -5,54 +5,99 @@ use crate::os::uefi;
55use crate :: ptr:: NonNull ;
66
77pub struct Stdin {
8- pending : Option < char > ,
8+ surrogate : Option < u16 > ,
9+ incomplete_utf8 : IncompleteUtf8 ,
10+ }
11+
12+ struct IncompleteUtf8 {
13+ bytes : [ u8 ; 4 ] ,
14+ len : u8 ,
15+ }
16+
17+ impl IncompleteUtf8 {
18+ pub const fn new ( ) -> IncompleteUtf8 {
19+ IncompleteUtf8 { bytes : [ 0 ; 4 ] , len : 0 }
20+ }
21+
22+ // Implemented for use in Stdin::read.
23+ fn read ( & mut self , buf : & mut [ u8 ] ) -> usize {
24+ // Write to buffer until the buffer is full or we run out of bytes.
25+ let to_write = crate :: cmp:: min ( buf. len ( ) , self . len as usize ) ;
26+ buf[ ..to_write] . copy_from_slice ( & self . bytes [ ..to_write] ) ;
27+
28+ // Rotate the remaining bytes if not enough remaining space in buffer.
29+ if usize:: from ( self . len ) > buf. len ( ) {
30+ self . bytes . copy_within ( to_write.., 0 ) ;
31+ self . len -= to_write as u8 ;
32+ } else {
33+ self . len = 0 ;
34+ }
35+
36+ to_write
37+ }
938}
1039
1140pub struct Stdout ;
1241pub struct Stderr ;
1342
1443impl Stdin {
1544 pub const fn new ( ) -> Stdin {
16- Stdin { pending : None }
45+ Stdin { surrogate : None , incomplete_utf8 : IncompleteUtf8 :: new ( ) }
1746 }
1847}
1948
2049impl io:: Read for Stdin {
21- fn read ( & mut self , mut buf : & mut [ u8 ] ) -> io:: Result < usize > {
22- let st : NonNull < r_efi :: efi :: SystemTable > = uefi :: env :: system_table ( ) . cast ( ) ;
23- let stdin = unsafe { ( * st . as_ptr ( ) ) . con_in } ;
24-
25- // Write any pending character
26- if let Some ( ch ) = self . pending {
27- if ch . len_utf8 ( ) > buf . len ( ) {
28- return Ok ( 0 ) ;
29- }
30- ch . encode_utf8 ( buf ) ;
31- buf = & mut buf[ ch . len_utf8 ( ) .. ] ;
32- self . pending = None ;
50+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
51+ // If there are bytes in the incomplete utf-8, start with those.
52+ // (No-op if there is nothing in the buffer.)
53+ let mut bytes_copied = self . incomplete_utf8 . read ( buf ) ;
54+
55+ let stdin : * mut r_efi :: protocols :: simple_text_input :: Protocol = unsafe {
56+ let st : NonNull < r_efi :: efi :: SystemTable > = uefi :: env :: system_table ( ) . cast ( ) ;
57+ ( * st . as_ptr ( ) ) . con_in
58+ } ;
59+
60+ if bytes_copied == buf. len ( ) {
61+ return Ok ( bytes_copied ) ;
3362 }
3463
35- // Try reading any pending data
36- let inp = read ( stdin) ?;
37-
38- // Check if the key is printiable character
39- if inp == 0x00 {
40- return Err ( io:: const_io_error!( io:: ErrorKind :: Interrupted , "Special Key Press" ) ) ;
64+ let ch = simple_text_input_read ( stdin) ?;
65+ // Only 1 character should be returned.
66+ let mut ch: Vec < Result < char , crate :: char:: DecodeUtf16Error > > =
67+ if let Some ( x) = self . surrogate . take ( ) {
68+ char:: decode_utf16 ( [ x, ch] ) . collect ( )
69+ } else {
70+ char:: decode_utf16 ( [ ch] ) . collect ( )
71+ } ;
72+
73+ if ch. len ( ) > 1 {
74+ return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , "invalid utf-16 sequence" ) ) ;
4175 }
4276
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 ) ;
77+ match ch. pop ( ) . unwrap ( ) {
78+ Err ( e) => {
79+ self . surrogate = Some ( e. unpaired_surrogate ( ) ) ;
80+ }
81+ Ok ( x) => {
82+ // This will always be > 0
83+ let buf_free_count = buf. len ( ) - bytes_copied;
84+ assert ! ( buf_free_count > 0 ) ;
85+
86+ if buf_free_count >= x. len_utf8 ( ) {
87+ // There is enough space in the buffer for the character.
88+ bytes_copied += x. encode_utf8 ( & mut buf[ bytes_copied..] ) . len ( ) ;
89+ } else {
90+ // There is not enough space in the buffer for the character.
91+ // Store the character in the incomplete buffer.
92+ self . incomplete_utf8 . len =
93+ x. encode_utf8 ( & mut self . incomplete_utf8 . bytes ) . len ( ) as u8 ;
94+ // write partial character to buffer.
95+ bytes_copied += self . incomplete_utf8 . read ( buf) ;
96+ }
97+ }
5198 }
5299
53- ch. encode_utf8 ( buf) ;
54-
55- Ok ( ch. len_utf8 ( ) )
100+ Ok ( bytes_copied)
56101 }
57102}
58103
@@ -94,11 +139,11 @@ impl io::Write for Stderr {
94139 }
95140}
96141
97- // UCS-2 character should occupy 3 bytes at most in UTF-8
98- pub const STDIN_BUF_SIZE : usize = 3 ;
142+ // UTF-16 character should occupy 4 bytes at most in UTF-8
143+ pub const STDIN_BUF_SIZE : usize = 4 ;
99144
100- pub fn is_ebadf ( err : & io:: Error ) -> bool {
101- err . raw_os_error ( ) == Some ( r_efi :: efi :: Status :: UNSUPPORTED . as_usize ( ) )
145+ pub fn is_ebadf ( _err : & io:: Error ) -> bool {
146+ false
102147}
103148
104149pub fn panic_output ( ) -> Option < impl io:: Write > {
@@ -116,6 +161,7 @@ fn write(
116161 } ;
117162
118163 let mut utf16: Vec < u16 > = utf8. encode_utf16 ( ) . collect ( ) ;
164+ // NULL terminate the string
119165 utf16. push ( 0 ) ;
120166
121167 unsafe { simple_text_output ( protocol, & mut utf16) } ?;
@@ -131,7 +177,9 @@ unsafe fn simple_text_output(
131177 if res. is_error ( ) { Err ( io:: Error :: from_raw_os_error ( res. as_usize ( ) ) ) } else { Ok ( ( ) ) }
132178}
133179
134- fn read ( stdin : * mut r_efi:: protocols:: simple_text_input:: Protocol ) -> io:: Result < u16 > {
180+ fn simple_text_input_read (
181+ stdin : * mut r_efi:: protocols:: simple_text_input:: Protocol ,
182+ ) -> io:: Result < u16 > {
135183 loop {
136184 match read_key_stroke ( stdin) {
137185 Ok ( x) => return Ok ( x. unicode_char ) ,
0 commit comments