aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/long_mode/display.rs60
-rw-r--r--test/long_mode/mod.rs45
2 files changed, 87 insertions, 18 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index da138bb..198a930 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -758,11 +758,15 @@ impl DisplaySink for alloc::string::String {
fn write_u8(&mut self, mut v: u8) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((8 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((8 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
+
self.reserve(printed_size);
let buf = unsafe { self.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
@@ -791,11 +795,15 @@ impl DisplaySink for alloc::string::String {
fn write_u16(&mut self, mut v: u16) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((16 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((16 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
+
self.reserve(printed_size);
let buf = unsafe { self.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
@@ -826,11 +834,15 @@ impl DisplaySink for alloc::string::String {
fn write_u32(&mut self, mut v: u32) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((32 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((32 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
+
self.reserve(printed_size);
let buf = unsafe { self.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
@@ -860,11 +872,15 @@ impl DisplaySink for alloc::string::String {
fn write_u64(&mut self, mut v: u64) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((64 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((64 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
+
self.reserve(printed_size);
let buf = unsafe { self.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
@@ -1140,10 +1156,13 @@ impl DisplaySink for BigEnoughString {
fn write_u8(&mut self, mut v: u8) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((8 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((8 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
let buf = unsafe { self.content.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
@@ -1172,10 +1191,13 @@ impl DisplaySink for BigEnoughString {
fn write_u16(&mut self, mut v: u16) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((16 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((16 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
let buf = unsafe { self.content.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
@@ -1205,10 +1227,13 @@ impl DisplaySink for BigEnoughString {
fn write_u32(&mut self, mut v: u32) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((32 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((32 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
let buf = unsafe { self.content.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
@@ -1238,10 +1263,13 @@ impl DisplaySink for BigEnoughString {
fn write_u64(&mut self, mut v: u64) -> Result<(), core::fmt::Error> {
// we can fairly easily predict the size of a formatted string here with lzcnt, which also
// means we can write directly into the correct offsets of the output string.
- let printed_size = (((64 - v.leading_zeros()) >> 2) + 1) as usize;
+ let mut printed_size = ((64 - v.leading_zeros() + 3) >> 2) as usize;
+ if printed_size == 0 {
+ printed_size = 1;
+ }
let buf = unsafe { self.content.as_mut_vec() };
- let p = buf.as_mut_ptr();
+ let p = unsafe { buf.as_mut_ptr().offset(buf.len() as isize) };
let mut curr = printed_size;
loop {
let digit = v % 16;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 8b01461..24df133 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -15,6 +15,19 @@ use std::fmt::Write;
use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction};
use yaxpeax_x86::long_mode::InstDecoder;
+#[test]
+#[cfg(feature="std")]
+fn test_write_hex_specialization() {
+ use crate::yaxpeax_x86::long_mode::DisplaySink;
+ for i in 0..0xffu8 {
+ let mut out = yaxpeax_x86::long_mode::BigEnoughString::new();
+ out.write_char('0').unwrap();
+ out.write_char('x').unwrap();
+ out.write_u8(i).unwrap();
+ assert_eq!(out.into_inner(), format!("0x{:x}", i));
+ }
+}
+
fn test_invalid(data: &[u8]) {
test_invalid_under(&InstDecoder::default(), data);
}
@@ -62,23 +75,51 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
text,
expected
);
+
let mut text2 = yaxpeax_x86::long_mode::BigEnoughString::new();
let mut out = yaxpeax_x86::long_mode::NoColorsSink {
out: &mut text2,
};
- instr.write_to(&mut out);
+ instr.write_to(&mut out).expect("printing succeeds");
core::mem::drop(out);
let text2 = text2.into_inner();
assert!(
text2 == text,
- "display error for {}:\n decoded: {:?} under decoder {}\n displayed: {}\n expected: {}\n",
+ "display error through NoColorsSink for {}:\n decoded: {:?} under decoder {}\n displayed: {}\n expected: {}\n",
hex,
instr,
decoder,
text2,
text,
);
+
+ let mut text3 = yaxpeax_x86::long_mode::BigEnoughString::new();
+ instr.write_to(&mut text3).expect("printing succeeds");
+ let text3 = text3.into_inner();
+
+ assert!(
+ text3 == text,
+ "display error through BigEnoughString for {}:\n decoded: {:?} under decoder {}\n displayed: {}\n expected: {}\n",
+ hex,
+ instr,
+ decoder,
+ text3,
+ text,
+ );
+
+ let mut text4 = String::new();
+ instr.write_to(&mut text4).expect("printing succeeds");
+
+ assert!(
+ text4 == text,
+ "display error through String for {}:\n decoded: {:?} under decoder {}\n displayed: {}\n expected: {}\n",
+ hex,
+ instr,
+ decoder,
+ text4,
+ text,
+ );
} else {
eprintln!("non-fmt build cannot compare text equality")
}