@@ -14,7 +14,7 @@ impl Stdin {
1414
1515impl io:: Read for Stdin {
1616 fn read ( & mut self , mut buf : & mut [ u8 ] ) -> io:: Result < usize > {
17- let mut written = 0 ;
17+ let mut count = 0 ;
1818
1919 while let Some ( ( out_byte, new_buf) ) = buf. split_first_mut ( ) {
2020 buf = new_buf;
@@ -25,10 +25,10 @@ impl io::Read for Stdin {
2525 }
2626
2727 * out_byte = byte as u8 ;
28- written += 1 ;
28+ count += 1 ;
2929 }
3030
31- Ok ( written )
31+ Ok ( count )
3232 }
3333}
3434
@@ -40,32 +40,48 @@ impl Stdout {
4040
4141impl io:: Write for Stdout {
4242 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
43- let mut count = 0 ;
43+ let mut written = 0 ;
4444
45- // HACK: VEXos holds an internal write buffer for serial that is flushed to USB1 roughly every
46- // millisecond by `vexTasksRun`. For writes larger than 2048 bytes, we must block until that buffer
47- // is flushed to USB1 before writing the rest of `buf`. In practice, this is fairly nonstandard for
48- // a `write` implementation but it avoids an guaranteed recursive panic when using macros such as
49- // `print!` to write large amounts of data to stdout at once.
45+ // HACK: VEXos holds an internal ringbuffer for serial writes that is flushed to USB1
46+ // roughly every millisecond by `vexTasksRun`. For writes larger than 2048 bytes, we
47+ // must block until that buffer is flushed to USB1 before writing the rest of `buf`.
48+ //
49+ // This is fairly nonstandard for a `write` implementation, but it avoids a guaranteed
50+ // recursive panic when using macros such as `print!` to write large amounts of data
51+ // (buf.len() > 2048) to stdout at once.
5052 for chunk in buf. chunks ( STDOUT_BUF_SIZE ) {
5153 if unsafe { vex_sdk:: vexSerialWriteFree ( STDIO_CHANNEL ) as usize } < chunk. len ( ) {
5254 self . flush ( ) . unwrap ( ) ;
5355 }
5456
55- count += unsafe { vex_sdk:: vexSerialWriteBuffer ( STDIO_CHANNEL , chunk. as_ptr ( ) , chunk. len ( ) as u32 ) } ;
56-
57+ let count = unsafe {
58+ vex_sdk:: vexSerialWriteBuffer ( STDIO_CHANNEL , chunk. as_ptr ( ) , chunk. len ( ) as u32 )
59+ } ;
5760 if count < 0 {
5861 return Err ( io:: Error :: new (
5962 io:: ErrorKind :: Uncategorized ,
6063 "Internal write error occurred." ,
6164 ) ) ;
6265 }
66+
67+ written += count;
68+
69+ // This is a sanity check to ensure that we don't end up with non-contiguous
70+ // buffer writes. e.g. a chunk gets only partially written, but we continue
71+ // attempting to write the remaining chunks.
72+ //
73+ // In practice, this should never really occur since the previous flush ensures
74+ // enough space in FIFO to write the entire chunk to vexSerialWriteBuffer.
75+ if count != chunk. len ( ) {
76+ break ;
77+ }
6378 }
6479
65- Ok ( count as usize )
80+ Ok ( written as usize )
6681 }
6782
6883 fn flush ( & mut self ) -> io:: Result < ( ) > {
84+ // This may block for up to a millisecond.
6985 unsafe {
7086 while ( vex_sdk:: vexSerialWriteFree ( STDIO_CHANNEL ) as usize ) != STDOUT_BUF_SIZE {
7187 vex_sdk:: vexTasksRun ( ) ;
0 commit comments