From 166695d09ab3c30a0147ac74aa856bae1f5542a8 Mon Sep 17 00:00:00 2001 From: iximeow Date: Tue, 18 Jun 2024 14:58:05 -0700 Subject: write_fixed_size impls for string and BigEnoughString --- src/long_mode/display.rs | 69 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index d7a80cb..575765c 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -371,14 +371,10 @@ pub enum TokenType { } pub trait DisplaySink: fmt::Write { - // /// may be optimized for writing strings of variable length. - // fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error>; fn write_fixed_size(&mut self, s: &str) -> Result<(), core::fmt::Error> { - for c in s.as_bytes().iter() { - self.write_char(*c as char)?; - } - Ok(()) + self.write_str(s) } + /// write a string to this sink that is less than 32 bytes. this is provided for optimization /// opportunities when writing a variable-length string with known max size. /// @@ -472,6 +468,37 @@ impl fmt::Write for BigEnoughString { // TODO: delete this whole thing? maybe? impl DisplaySink for alloc::string::String { + fn write_fixed_size(&mut self, s: &str) -> Result<(), core::fmt::Error> { + self.reserve(s.len()); + let buf = unsafe { self.as_mut_vec() }; + let new_bytes = s.as_bytes(); + + if new_bytes.len() == 0 { + unsafe { core::hint::unreachable_unchecked() } + } + + if new_bytes.len() >= 16 { + unsafe { core::hint::unreachable_unchecked() } + } + + unsafe { + let dest = buf.as_mut_ptr().offset(buf.len() as isize); + let src = new_bytes.as_ptr(); + + let mut rem = new_bytes.len() as isize; + + dest.offset(0 as isize).write(new_bytes[0]); + for i in 1..new_bytes.len() { + unsafe { + dest.offset(i as isize).write(new_bytes[i]); + } + } + + buf.set_len(buf.len() + new_bytes.len()); + } + + Ok(()) + } unsafe fn write_lt_32(&mut self, s: &str) -> Result<(), fmt::Error> { self.reserve(s.len()); @@ -686,6 +713,36 @@ impl DisplaySink for alloc::string::String { } impl DisplaySink for BigEnoughString { + fn write_fixed_size(&mut self, s: &str) -> Result<(), core::fmt::Error> { + let buf = unsafe { self.content.as_mut_vec() }; + let new_bytes = s.as_bytes(); + + if new_bytes.len() == 0 { + unsafe { core::hint::unreachable_unchecked() } + } + + if new_bytes.len() >= 16 { + unsafe { core::hint::unreachable_unchecked() } + } + + unsafe { + let dest = buf.as_mut_ptr().offset(buf.len() as isize); + let src = new_bytes.as_ptr(); + + let mut rem = new_bytes.len() as isize; + + dest.offset(0 as isize).write(new_bytes[0]); + for i in 1..new_bytes.len() { + unsafe { + dest.offset(i as isize).write(new_bytes[i]); + } + } + + buf.set_len(buf.len() + new_bytes.len()); + } + + Ok(()) + } unsafe fn write_lt_32(&mut self, s: &str) -> Result<(), fmt::Error> { // SAFETY: todo let buf = unsafe { self.content.as_mut_vec() }; -- cgit v1.1