impl Render for u128/i128

This commit is contained in:
Kogia-sima 2020-06-20 21:21:51 +09:00
parent ed8f237c4e
commit ea080e8a6c
2 changed files with 166 additions and 11 deletions

View File

@ -189,6 +189,71 @@ unsafe fn write_u64(mut n: u64, buf: *mut u8) -> usize {
}
}
unsafe fn write_u128(n: u128, buf: *mut u8) -> usize {
if n <= std::u64::MAX as u128 {
write_u64(n as u64, buf)
} else if n < 100000000000000000000000000000000 {
let a0 = (n / 10000000000000000) as u64;
let a1 = (n % 10000000000000000) as u64;
let b0 = (a1 / 100000000) as u32;
let b1 = (a1 / 100000000) as u32;
let c0 = (b0 / 10000) as u16;
let c1 = (b0 % 10000) as u16;
let c2 = (b1 / 10000) as u16;
let c3 = (b1 % 10000) as u16;
let l = write_u64(a0, buf);
write_small_pad(c0, buf.add(l));
write_small_pad(c1, buf.add(l + 4));
write_small_pad(c2, buf.add(l + 8));
write_small_pad(c3, buf.add(l + 12));
l + 16
} else {
let a0 = (n / 100000000000000000000000000000000) as u32; // 1 to 3402823
let a1 = n % 100000000000000000000000000000000;
let b0 = (a1 / 10000000000000000) as u64;
let b1 = (a1 % 10000000000000000) as u64;
let c0 = (b0 / 100000000) as u32;
let c1 = (b0 % 100000000) as u32;
let c2 = (b1 / 100000000) as u32;
let c3 = (b1 % 100000000) as u32;
let d0 = (c0 / 10000) as u16;
let d1 = (c0 % 10000) as u16;
let d2 = (c1 / 10000) as u16;
let d3 = (c1 % 10000) as u16;
let d4 = (c2 / 10000) as u16;
let d5 = (c2 % 10000) as u16;
let d6 = (c3 / 10000) as u16;
let d7 = (c3 % 10000) as u16;
let l = if a0 < 10000 {
write_small(a0 as u16, buf)
} else {
let b0 = (a0 / 10000) as u16;
let b1 = (a0 % 10000) as u16;
let l = write_small(b0, buf);
write_small_pad(b1, buf.add(l));
l + 4
};
write_small_pad(d0, buf.add(l));
write_small_pad(d1, buf.add(l + 4));
write_small_pad(d2, buf.add(l + 8));
write_small_pad(d3, buf.add(l + 12));
write_small_pad(d4, buf.add(l + 16));
write_small_pad(d5, buf.add(l + 20));
write_small_pad(d6, buf.add(l + 24));
write_small_pad(d7, buf.add(l + 28));
l + 32
}
}
pub trait Integer {
const MAX_LEN: usize;
unsafe fn write_to(self, buf: *mut u8) -> usize;
@ -227,6 +292,7 @@ impl_integer!(u8, i8, u8, write_u8, 3);
impl_integer!(u16, i16, u16, write_u16, 5);
impl_integer!(u32, i32, u32, write_u32, 10);
impl_integer!(u64, i64, u64, write_u64, 20);
impl_integer!(u128, i128, u128, write_u128, 39);
#[cfg(target_pointer_width = "16")]
impl_integer!(usize, isize, u16, write_u16, 6);
@ -282,17 +348,21 @@ mod tests {
fn $name() {
use super::Integer;
unsafe fn test_write(val: $type, buf: &mut Vec<u8>) {
let l = val.write_to(buf.as_mut_ptr());
buf.set_len(l);
assert_eq!(
std::str::from_utf8_unchecked(&*buf),
format!("{}", val)
);
}
let mut buf = Vec::with_capacity(<$type>::MAX_LEN);
$(
unsafe {
let l = ($value as $type).write_to(buf.as_mut_ptr());
buf.set_len(l);
assert_eq!(
std::str::from_utf8_unchecked(&*buf),
format!("{}", $value as $type)
);
}
)*
unsafe {
$(
test_write($value as $type, &mut buf);
)*
}
}
}
}
@ -350,8 +420,93 @@ mod tests {
18446744073709551615
);
make_test!(
test_u128,
u128,
0,
9,
10,
99,
100,
999,
1000,
9999,
10000,
99999,
100000,
999999,
1000000,
9999999,
10000000,
99999999,
100000000,
999999999,
1000000000,
9999999999,
10000000000,
99999999999,
100000000000,
999999999999,
1000000000000,
9999999999999,
10000000000000,
99999999999999,
100000000000000,
999999999999999,
1000000000000000,
9999999999999999,
10000000000000000,
99999999999999999,
100000000000000000,
999999999999999999,
1000000000000000000,
9999999999999999999,
10000000000000000000,
99999999999999999999,
100000000000000000000,
999999999999999999999,
1000000000000000000000,
9999999999999999999999,
10000000000000000000000,
99999999999999999999999,
100000000000000000000000,
100000000000000000000000,
999999999999999999999999,
1000000000000000000000000,
9999999999999999999999999,
10000000000000000000000000,
99999999999999999999999999,
100000000000000000000000000,
999999999999999999999999999,
1000000000000000000000000000,
9999999999999999999999999999,
10000000000000000000000000000,
99999999999999999999999999999,
100000000000000000000000000000,
999999999999999999999999999999,
1000000000000000000000000000000,
9999999999999999999999999999999,
10000000000000000000000000000000,
99999999999999999999999999999999,
100000000000000000000000000000000,
999999999999999999999999999999999,
1000000000000000000000000000000000,
9999999999999999999999999999999999,
10000000000000000000000000000000000,
99999999999999999999999999999999999,
100000000000000000000000000000000000,
999999999999999999999999999999999999,
1000000000000000000000000000000000000,
9999999999999999999999999999999999999,
10000000000000000000000000000000000000,
99999999999999999999999999999999999999,
100000000000000000000000000000000000000,
340282366920938463463374607431768211455
);
make_test!(test_i8, i8, std::i8::MIN, std::i8::MAX);
make_test!(test_i16, i16, std::i16::MIN, std::i16::MAX);
make_test!(test_i32, i32, std::i32::MIN, std::i32::MAX);
make_test!(test_i64, i64, std::i64::MIN, std::i64::MAX);
make_test!(test_i128, i128, std::i128::MIN, std::i128::MAX);
}

View File

@ -172,7 +172,7 @@ macro_rules! render_int {
}
}
render_int!(u8, u16, u32, u64, i8, i16, i32, i64, usize, isize);
render_int!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize);
impl Render for f32 {
#[inline]