diff --git a/src/console.rs b/src/console.rs index ecd7ad1..ae1b826 100644 --- a/src/console.rs +++ b/src/console.rs @@ -16,33 +16,63 @@ mod allow_nr { pub const SHARE_BUFFER: usize = 1; } +const BUFFER_SIZE: usize = 1024; + pub struct Console { - allow_buffer: [u8; 64], + allow_buffer: [u8; BUFFER_SIZE], + count_pending: usize, } impl Console { pub fn new() -> Console { Console { - allow_buffer: [0; 64], + allow_buffer: [0; BUFFER_SIZE], + count_pending: 0, } } + fn is_empty(&self) -> bool { + self.count_pending == 0 + } + + fn is_full(&self) -> bool { + self.allow_buffer.len() == self.count_pending + } + + fn available_len(&self) -> usize { + self.allow_buffer.len() - self.count_pending + } + pub fn write>(&mut self, text: S) { let mut not_written_yet = text.as_ref(); while !not_written_yet.is_empty() { - let num_bytes_to_print = self.allow_buffer.len().min(not_written_yet.len()); - self.allow_buffer[..num_bytes_to_print] + let num_bytes_to_print = self.available_len().min(not_written_yet.len()); + self.allow_buffer[self.count_pending..(self.count_pending + num_bytes_to_print)] .copy_from_slice(¬_written_yet[..num_bytes_to_print]); - self.flush(num_bytes_to_print); + self.count_pending += num_bytes_to_print; + + if self.is_full() { + self.flush(); + } + not_written_yet = ¬_written_yet[num_bytes_to_print..]; } } - fn flush(&mut self, num_bytes_to_print: usize) { + pub fn flush(&mut self) { + if self.is_empty() { + // Don't trigger any syscall if the buffer is empty. + return; + } + + let count = self.count_pending; + // Clear the buffer even in case of error, to avoid an infinite loop. + self.count_pending = 0; + let result = syscalls::allow( DRIVER_NUMBER, allow_nr::SHARE_BUFFER, - &mut self.allow_buffer[..num_bytes_to_print], + &mut self.allow_buffer[..count], ); if result.is_err() { return; @@ -59,8 +89,7 @@ impl Console { return; } - let result_code = - unsafe { syscalls::command(DRIVER_NUMBER, command_nr::WRITE, num_bytes_to_print, 0) }; + let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::WRITE, count, 0) }; if result_code < 0 { return; } @@ -69,6 +98,12 @@ impl Console { } } +impl Drop for Console { + fn drop(&mut self) { + self.flush(); + } +} + impl fmt::Write for Console { fn write_str(&mut self, string: &str) -> Result<(), fmt::Error> { self.write(string);