Skip to content

Commit

Permalink
Display formatting support (#584) (#603)
Browse files Browse the repository at this point in the history
* Display formatting support (#584)

* Update uint/src/uint.rs

Co-authored-by: Niklas Adolfsson <[email protected]>

Co-authored-by: Andronik <[email protected]>
Co-authored-by: Niklas Adolfsson <[email protected]>
  • Loading branch information
3 people authored Jan 27, 2022
1 parent a855f4d commit 8f5bf54
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 36 deletions.
81 changes: 48 additions & 33 deletions uint/src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,7 @@ macro_rules! impl_try_from_for_primitive {
fn try_from(u: $from) -> $crate::core_::result::Result<$to, &'static str> {
let $from(arr) = u;
if !u.fits_word() || arr[0] > <$to>::max_value() as u64 {
Err(concat!(
"integer overflow when casting to ",
stringify!($to)
))
Err(concat!("integer overflow when casting to ", stringify!($to)))
} else {
Ok(arr[0] as $to)
}
Expand All @@ -223,9 +220,7 @@ macro_rules! uint_overflowing_binop {
let mut ret = [0u64; $n_words];
let ret_ptr = &mut ret as *mut [u64; $n_words] as *mut u64;
let mut carry = 0u64;
$crate::static_assertions::const_assert!(
core::isize::MAX as usize / core::mem::size_of::<u64>() > $n_words
);
$crate::static_assertions::const_assert!(core::isize::MAX as usize / core::mem::size_of::<u64>() > $n_words);

// `unroll!` is recursive, but doesn’t use `$crate::unroll`, so we need to ensure that it
// is in scope unqualified.
Expand Down Expand Up @@ -321,8 +316,7 @@ macro_rules! uint_full_mul_reg {
#[doc(hidden)]
macro_rules! uint_overflowing_mul {
($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => {{
let ret: [u64; $n_words * 2] =
$crate::uint_full_mul_reg!($name, $n_words, $self_expr, $other);
let ret: [u64; $n_words * 2] = $crate::uint_full_mul_reg!($name, $n_words, $self_expr, $other);

// The safety of this is enforced by the compiler
let ret: [[u64; $n_words]; 2] = unsafe { $crate::core_::mem::transmute(ret) };
Expand Down Expand Up @@ -1307,6 +1301,44 @@ macro_rules! construct_uint {

$name(ret)
}

fn fmt_hex(&self, f: &mut $crate::core_::fmt::Formatter, is_lower: bool) -> $crate::core_::fmt::Result {
let &$name(ref data) = self;
// special case.
if self.is_zero() {
return f.pad_integral(true, "0x", "0");
}

let mut latch = false;
let mut buf = [0_u8; $n_words * 16];
let mut i = 0;
for ch in data.iter().rev() {
for x in 0..16 {
// nibble < 16
let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64);
if !latch {
latch = nibble != 0;
}

if latch {
// nibble is `'0'..'9' 'a'..'f' 'A'..'F'` because nibble < 16
let nibble = match nibble {
0..=9 => nibble as u8 + b'0',
_ if is_lower => nibble as u8 - 10 + b'a',
_ => nibble as u8 - 10 + b'A',
};
buf[i] = nibble;
i += 1;
}
}
}

// sequence of `'0'..'9' 'a'..'f' 'A'..'F'` chars is guaranteed to be a valid UTF8 string
let s = unsafe {
$crate::core_::str::from_utf8_unchecked(&buf[0..i])
};
f.pad_integral(true, "0x", s)
}
}

impl $crate::core_::convert::From<$name> for [u8; $n_words * 8] {
Expand Down Expand Up @@ -1673,35 +1705,19 @@ macro_rules! construct_uint {
let s = unsafe {
$crate::core_::str::from_utf8_unchecked(&buf[i..])
};
f.write_str(s)
f.pad_integral(true, "", s)
}
}

impl $crate::core_::fmt::LowerHex for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
let &$name(ref data) = self;
if f.alternate() {
$crate::core_::write!(f, "0x")?;
}
// special case.
if self.is_zero() {
return $crate::core_::write!(f, "0");
}

let mut latch = false;
for ch in data.iter().rev() {
for x in 0..16 {
let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64);
if !latch {
latch = nibble != 0;
}
self.fmt_hex(f, true)
}
}

if latch {
$crate::core_::write!(f, "{:x}", nibble)?;
}
}
}
Ok(())
impl $crate::core_::fmt::UpperHex for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
self.fmt_hex(f, false)
}
}

Expand Down Expand Up @@ -1795,7 +1811,6 @@ macro_rules! impl_quickcheck_arbitrary_for_uint {
($uint: ty, $n_bytes: tt) => {};
}


#[cfg(feature = "arbitrary")]
#[macro_export]
#[doc(hidden)]
Expand Down
20 changes: 17 additions & 3 deletions uint/tests/uint_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,13 +531,27 @@ fn uint256_from_dec_str() {

#[test]
fn display_uint() {
let s = "12345678987654321023456789";
assert_eq!(format!("{}", U256::from_dec_str(s).unwrap()), s);
let s = U256::from_dec_str("12345678987654321023456789").unwrap();
assert_eq!(format!("{}", s), "12345678987654321023456789");
assert_eq!(format!("{:x}", s), "a364c995584f929f39615");
assert_eq!(format!("{:X}", s), "A364C995584F929F39615");
assert_eq!(format!("{:032}", s), "00000012345678987654321023456789");
assert_eq!(format!("{:032x}", s), "00000000000a364c995584f929f39615");
assert_eq!(format!("{:032X}", s), "00000000000A364C995584F929F39615");
assert_eq!(format!("{:#032x}", s), "0x000000000a364c995584f929f39615");
assert_eq!(format!("{:#032X}", s), "0x000000000A364C995584F929F39615");
}

#[test]
fn display_uint_zero() {
assert_eq!(format!("{}", U256::from(0)), "0");
let s = U256::from(0);
assert_eq!(format!("{}", s), "0");
assert_eq!(format!("{:x}", s), "0");
assert_eq!(format!("{:X}", s), "0");
assert_eq!(format!("{:032x}", s), "00000000000000000000000000000000");
assert_eq!(format!("{:032X}", s), "00000000000000000000000000000000");
assert_eq!(format!("{:#032x}", s), "0x000000000000000000000000000000");
assert_eq!(format!("{:#032X}", s), "0x000000000000000000000000000000");
}

#[test]
Expand Down

0 comments on commit 8f5bf54

Please sign in to comment.