1#![doc(html_root_url = "https://docs.rs/itoa/1.0.17")]
41#![no_std]
42#![allow(
43 clippy::cast_lossless,
44 clippy::cast_possible_truncation,
45 clippy::cast_sign_loss,
46 clippy::expl_impl_clone_on_copy,
47 clippy::identity_op,
48 clippy::items_after_statements,
49 clippy::must_use_candidate,
50 clippy::needless_doctest_main,
51 clippy::unreadable_literal
52)]
53
54mod u128_ext;
55
56use core::hint;
57use core::mem::{self, MaybeUninit};
58use core::ptr;
59use core::str;
60#[cfg(feature = "no-panic")]
61use no_panic::no_panic;
62
63pub struct Buffer {
74 bytes: [MaybeUninit<u8>; i128::MAX_STR_LEN],
75}
76
77impl Default for Buffer {
78 #[inline]
79 fn default() -> Buffer {
80 Buffer::new()
81 }
82}
83
84impl Copy for Buffer {}
85
86#[allow(clippy::non_canonical_clone_impl)]
87impl Clone for Buffer {
88 #[inline]
89 fn clone(&self) -> Self {
90 Buffer::new()
91 }
92}
93
94impl Buffer {
95 #[inline]
98 #[cfg_attr(feature = "no-panic", no_panic)]
99 pub fn new() -> Buffer {
100 let bytes = [MaybeUninit::<u8>::uninit(); i128::MAX_STR_LEN];
101 Buffer { bytes }
102 }
103
104 #[cfg_attr(feature = "no-panic", no_panic)]
107 pub fn format<I: Integer>(&mut self, i: I) -> &str {
108 let string = i.write(unsafe {
109 &mut *&raw mut self.bytesptr::addr_of_mut!(self.bytes).cast::<<I as private::Sealed>::Buffer>()
110 });
111 if string.len() > I::MAX_STR_LEN {
112 unsafe { hint::unreachable_unchecked() };
113 }
114 string
115 }
116}
117
118pub trait Integer: private::Sealed {
122 const MAX_STR_LEN: usize;
125}
126
127mod private {
129 #[doc(hidden)]
130 pub trait Sealed: Copy {
131 #[doc(hidden)]
132 type Buffer: 'static;
133 fn write(self, buf: &mut Self::Buffer) -> &str;
134 }
135}
136
137macro_rules! impl_Integer {
138 ($Signed:ident, $Unsigned:ident) => {
139 const _: () = {
140 assert!($Signed::MIN < 0, "need signed");
141 assert!($Unsigned::MIN == 0, "need unsigned");
142 assert!($Signed::BITS == $Unsigned::BITS, "need counterparts");
143 };
144
145 impl Integer for $Unsigned {
146 const MAX_STR_LEN: usize = $Unsigned::MAX.ilog10() as usize + 1;
147 }
148
149 impl private::Sealed for $Unsigned {
150 type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
151
152 #[inline]
153 #[cfg_attr(feature = "no-panic", no_panic)]
154 fn write(self, buf: &mut Self::Buffer) -> &str {
155 let offset = Unsigned::fmt(self, buf);
156 unsafe { slice_buffer_to_str(buf, offset) }
158 }
159 }
160
161 impl Integer for $Signed {
162 const MAX_STR_LEN: usize = $Signed::MAX.ilog10() as usize + 2;
163 }
164
165 impl private::Sealed for $Signed {
166 type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
167
168 #[inline]
169 #[cfg_attr(feature = "no-panic", no_panic)]
170 fn write(self, buf: &mut Self::Buffer) -> &str {
171 let mut offset = Self::MAX_STR_LEN - $Unsigned::MAX_STR_LEN;
172 offset += Unsigned::fmt(
173 self.unsigned_abs(),
174 (&mut buf[offset..]).try_into().unwrap(),
175 );
176 if self < 0 {
177 offset -= 1;
178 buf[offset].write(b'-');
179 }
180 unsafe { slice_buffer_to_str(buf, offset) }
182 }
183 }
184 };
185}
186
187const _: () =
{
if !(i8::MIN < 0) {
{ ::core::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u8::MIN == 0) {
{ ::core::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i8::BITS == u8::BITS) {
{
::core::panicking::panic_fmt(format_args!("need counterparts"));
}
};
};
impl Integer for u8 {
const MAX_STR_LEN: usize = u8::MAX.ilog10() as usize + 1;
}
impl private::Sealed for u8 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let offset = Unsigned::fmt(self, buf);
unsafe { slice_buffer_to_str(buf, offset) }
}
}
impl Integer for i8 {
const MAX_STR_LEN: usize = i8::MAX.ilog10() as usize + 2;
}
impl private::Sealed for i8 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let mut offset = Self::MAX_STR_LEN - u8::MAX_STR_LEN;
offset +=
Unsigned::fmt(self.unsigned_abs(),
(&mut buf[offset..]).try_into().unwrap());
if self < 0 { offset -= 1; buf[offset].write(b'-'); }
unsafe { slice_buffer_to_str(buf, offset) }
}
}impl_Integer!(i8, u8);
188const _: () =
{
if !(i16::MIN < 0) {
{ ::core::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u16::MIN == 0) {
{ ::core::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i16::BITS == u16::BITS) {
{
::core::panicking::panic_fmt(format_args!("need counterparts"));
}
};
};
impl Integer for u16 {
const MAX_STR_LEN: usize = u16::MAX.ilog10() as usize + 1;
}
impl private::Sealed for u16 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let offset = Unsigned::fmt(self, buf);
unsafe { slice_buffer_to_str(buf, offset) }
}
}
impl Integer for i16 {
const MAX_STR_LEN: usize = i16::MAX.ilog10() as usize + 2;
}
impl private::Sealed for i16 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let mut offset = Self::MAX_STR_LEN - u16::MAX_STR_LEN;
offset +=
Unsigned::fmt(self.unsigned_abs(),
(&mut buf[offset..]).try_into().unwrap());
if self < 0 { offset -= 1; buf[offset].write(b'-'); }
unsafe { slice_buffer_to_str(buf, offset) }
}
}impl_Integer!(i16, u16);
189const _: () =
{
if !(i32::MIN < 0) {
{ ::core::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u32::MIN == 0) {
{ ::core::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i32::BITS == u32::BITS) {
{
::core::panicking::panic_fmt(format_args!("need counterparts"));
}
};
};
impl Integer for u32 {
const MAX_STR_LEN: usize = u32::MAX.ilog10() as usize + 1;
}
impl private::Sealed for u32 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let offset = Unsigned::fmt(self, buf);
unsafe { slice_buffer_to_str(buf, offset) }
}
}
impl Integer for i32 {
const MAX_STR_LEN: usize = i32::MAX.ilog10() as usize + 2;
}
impl private::Sealed for i32 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let mut offset = Self::MAX_STR_LEN - u32::MAX_STR_LEN;
offset +=
Unsigned::fmt(self.unsigned_abs(),
(&mut buf[offset..]).try_into().unwrap());
if self < 0 { offset -= 1; buf[offset].write(b'-'); }
unsafe { slice_buffer_to_str(buf, offset) }
}
}impl_Integer!(i32, u32);
190const _: () =
{
if !(i64::MIN < 0) {
{ ::core::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u64::MIN == 0) {
{ ::core::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i64::BITS == u64::BITS) {
{
::core::panicking::panic_fmt(format_args!("need counterparts"));
}
};
};
impl Integer for u64 {
const MAX_STR_LEN: usize = u64::MAX.ilog10() as usize + 1;
}
impl private::Sealed for u64 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let offset = Unsigned::fmt(self, buf);
unsafe { slice_buffer_to_str(buf, offset) }
}
}
impl Integer for i64 {
const MAX_STR_LEN: usize = i64::MAX.ilog10() as usize + 2;
}
impl private::Sealed for i64 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let mut offset = Self::MAX_STR_LEN - u64::MAX_STR_LEN;
offset +=
Unsigned::fmt(self.unsigned_abs(),
(&mut buf[offset..]).try_into().unwrap());
if self < 0 { offset -= 1; buf[offset].write(b'-'); }
unsafe { slice_buffer_to_str(buf, offset) }
}
}impl_Integer!(i64, u64);
191const _: () =
{
if !(i128::MIN < 0) {
{ ::core::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u128::MIN == 0) {
{ ::core::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i128::BITS == u128::BITS) {
{
::core::panicking::panic_fmt(format_args!("need counterparts"));
}
};
};
impl Integer for u128 {
const MAX_STR_LEN: usize = u128::MAX.ilog10() as usize + 1;
}
impl private::Sealed for u128 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let offset = Unsigned::fmt(self, buf);
unsafe { slice_buffer_to_str(buf, offset) }
}
}
impl Integer for i128 {
const MAX_STR_LEN: usize = i128::MAX.ilog10() as usize + 2;
}
impl private::Sealed for i128 {
type Buffer = [MaybeUninit<u8>; Self::MAX_STR_LEN];
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
let mut offset = Self::MAX_STR_LEN - u128::MAX_STR_LEN;
offset +=
Unsigned::fmt(self.unsigned_abs(),
(&mut buf[offset..]).try_into().unwrap());
if self < 0 { offset -= 1; buf[offset].write(b'-'); }
unsafe { slice_buffer_to_str(buf, offset) }
}
}impl_Integer!(i128, u128);
192
193macro_rules! impl_Integer_size {
194 ($t:ty as $primitive:ident #[cfg(target_pointer_width = $width:literal)]) => {
195 #[cfg(target_pointer_width = $width)]
196 impl Integer for $t {
197 const MAX_STR_LEN: usize = <$primitive as Integer>::MAX_STR_LEN;
198 }
199
200 #[cfg(target_pointer_width = $width)]
201 impl private::Sealed for $t {
202 type Buffer = <$primitive as private::Sealed>::Buffer;
203
204 #[inline]
205 #[cfg_attr(feature = "no-panic", no_panic)]
206 fn write(self, buf: &mut Self::Buffer) -> &str {
207 (self as $primitive).write(buf)
208 }
209 }
210 };
211}
212
213impl_Integer_size!(isize as i16 #[cfg(target_pointer_width = "16")]);
214impl_Integer_size!(usize as u16 #[cfg(target_pointer_width = "16")]);
215impl_Integer_size!(isize as i32 #[cfg(target_pointer_width = "32")]);
216impl_Integer_size!(usize as u32 #[cfg(target_pointer_width = "32")]);
217impl Integer for isize {
const MAX_STR_LEN: usize = <i64 as Integer>::MAX_STR_LEN;
}
impl private::Sealed for isize {
type Buffer = <i64 as private::Sealed>::Buffer;
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
(self as i64).write(buf)
}
}impl_Integer_size!(isize as i64 #[cfg(target_pointer_width = "64")]);
218impl Integer for usize {
const MAX_STR_LEN: usize = <u64 as Integer>::MAX_STR_LEN;
}
impl private::Sealed for usize {
type Buffer = <u64 as private::Sealed>::Buffer;
#[inline]
fn write(self, buf: &mut Self::Buffer) -> &str {
(self as u64).write(buf)
}
}impl_Integer_size!(usize as u64 #[cfg(target_pointer_width = "64")]);
219
220#[repr(C, align(2))]
221struct DecimalPairs([u8; 200]);
222
223static DECIMAL_PAIRS: DecimalPairs = DecimalPairs(
225 *b"0001020304050607080910111213141516171819\
226 2021222324252627282930313233343536373839\
227 4041424344454647484950515253545556575859\
228 6061626364656667686970717273747576777879\
229 8081828384858687888990919293949596979899",
230);
231
232fn divmod100(value: u32) -> (u32, u32) {
234 if true {
if !(value < 10_000) {
::core::panicking::panic("assertion failed: value < 10_000")
};
};debug_assert!(value < 10_000);
235 const EXP: u32 = 19; const SIG: u32 = (1 << EXP) / 100 + 1;
237 let div = (value * SIG) >> EXP; (div, value - div * 100)
239}
240
241#[cfg_attr(feature = "no-panic", no_panic)]
249unsafe fn slice_buffer_to_str(buf: &[MaybeUninit<u8>], offset: usize) -> &str {
250 let written = unsafe { buf.get_unchecked(offset..) };
252 unsafe { str::from_utf8_unchecked(&*(written as *const [MaybeUninit<u8>] as *const [u8])) }
255}
256
257trait Unsigned: Integer {
258 fn fmt(self, buf: &mut Self::Buffer) -> usize;
259}
260
261macro_rules! impl_Unsigned {
262 ($Unsigned:ident) => {
263 impl Unsigned for $Unsigned {
264 #[cfg_attr(feature = "no-panic", no_panic)]
265 fn fmt(self, buf: &mut Self::Buffer) -> usize {
266 let mut offset = buf.len();
268 let mut remain = self;
270
271 while mem::size_of::<Self>() > 1
274 && remain
275 > 999
276 .try_into()
277 .expect("branch is not hit for types that cannot fit 999 (u8)")
278 {
279 offset -= 4;
280
281 let scale: Self = 1_00_00
283 .try_into()
284 .expect("branch is not hit for types that cannot fit 1E4 (u8)");
285 let quad = remain % scale;
286 remain /= scale;
287 let (pair1, pair2) = divmod100(quad as u32);
288 unsafe {
289 buf[offset + 0]
290 .write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 + 0));
291 buf[offset + 1]
292 .write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 + 1));
293 buf[offset + 2]
294 .write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 + 0));
295 buf[offset + 3]
296 .write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 + 1));
297 }
298 }
299
300 if remain > 9 {
302 offset -= 2;
303
304 let (last, pair) = divmod100(remain as u32);
305 remain = last as Self;
306 unsafe {
307 buf[offset + 0]
308 .write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 + 0));
309 buf[offset + 1]
310 .write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 + 1));
311 }
312 }
313
314 if remain != 0 || self == 0 {
316 offset -= 1;
317
318 let last = remain as u8 & 15;
321 buf[offset].write(b'0' + last);
322 }
324
325 offset
326 }
327 }
328 };
329}
330
331impl Unsigned for u8 {
fn fmt(self, buf: &mut Self::Buffer) -> usize {
let mut offset = buf.len();
let mut remain = self;
while mem::size_of::<Self>() > 1 &&
remain >
999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)")
{
offset -= 4;
let scale: Self =
1_00_00.try_into().expect("branch is not hit for types that cannot fit 1E4 (u8)");
let quad = remain % scale;
remain /= scale;
let (pair1, pair2) = divmod100(quad as u32);
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
1));
buf[offset +
2].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
0));
buf[offset +
3].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
1));
}
}
if remain > 9 {
offset -= 2;
let (last, pair) = divmod100(remain as u32);
remain = last as Self;
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
1));
}
}
if remain != 0 || self == 0 {
offset -= 1;
let last = remain as u8 & 15;
buf[offset].write(b'0' + last);
}
offset
}
}impl_Unsigned!(u8);
332impl Unsigned for u16 {
fn fmt(self, buf: &mut Self::Buffer) -> usize {
let mut offset = buf.len();
let mut remain = self;
while mem::size_of::<Self>() > 1 &&
remain >
999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)")
{
offset -= 4;
let scale: Self =
1_00_00.try_into().expect("branch is not hit for types that cannot fit 1E4 (u8)");
let quad = remain % scale;
remain /= scale;
let (pair1, pair2) = divmod100(quad as u32);
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
1));
buf[offset +
2].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
0));
buf[offset +
3].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
1));
}
}
if remain > 9 {
offset -= 2;
let (last, pair) = divmod100(remain as u32);
remain = last as Self;
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
1));
}
}
if remain != 0 || self == 0 {
offset -= 1;
let last = remain as u8 & 15;
buf[offset].write(b'0' + last);
}
offset
}
}impl_Unsigned!(u16);
333impl Unsigned for u32 {
fn fmt(self, buf: &mut Self::Buffer) -> usize {
let mut offset = buf.len();
let mut remain = self;
while mem::size_of::<Self>() > 1 &&
remain >
999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)")
{
offset -= 4;
let scale: Self =
1_00_00.try_into().expect("branch is not hit for types that cannot fit 1E4 (u8)");
let quad = remain % scale;
remain /= scale;
let (pair1, pair2) = divmod100(quad as u32);
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
1));
buf[offset +
2].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
0));
buf[offset +
3].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
1));
}
}
if remain > 9 {
offset -= 2;
let (last, pair) = divmod100(remain as u32);
remain = last as Self;
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
1));
}
}
if remain != 0 || self == 0 {
offset -= 1;
let last = remain as u8 & 15;
buf[offset].write(b'0' + last);
}
offset
}
}impl_Unsigned!(u32);
334impl Unsigned for u64 {
fn fmt(self, buf: &mut Self::Buffer) -> usize {
let mut offset = buf.len();
let mut remain = self;
while mem::size_of::<Self>() > 1 &&
remain >
999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)")
{
offset -= 4;
let scale: Self =
1_00_00.try_into().expect("branch is not hit for types that cannot fit 1E4 (u8)");
let quad = remain % scale;
remain /= scale;
let (pair1, pair2) = divmod100(quad as u32);
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 +
1));
buf[offset +
2].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
0));
buf[offset +
3].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 +
1));
}
}
if remain > 9 {
offset -= 2;
let (last, pair) = divmod100(remain as u32);
remain = last as Self;
unsafe {
buf[offset +
0].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
0));
buf[offset +
1].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 +
1));
}
}
if remain != 0 || self == 0 {
offset -= 1;
let last = remain as u8 & 15;
buf[offset].write(b'0' + last);
}
offset
}
}impl_Unsigned!(u64);
335
336impl Unsigned for u128 {
337 #[cfg_attr(feature = "no-panic", no_panic)]
338 fn fmt(self, buf: &mut Self::Buffer) -> usize {
339 if self == 0 {
342 let offset = buf.len() - 1;
343 buf[offset].write(b'0');
344 return offset;
345 }
346 let (quot_1e16, mod_1e16) = div_rem_1e16(self);
348 let (mut remain, mut offset) = if quot_1e16 == 0 {
349 (mod_1e16, u128::MAX_STR_LEN)
350 } else {
351 enc_16lsd::<{ u128::MAX_STR_LEN - 16 }>(buf, mod_1e16);
353
354 let (quot2, mod2) = div_rem_1e16(quot_1e16);
356 if quot2 == 0 {
357 (mod2, u128::MAX_STR_LEN - 16)
358 } else {
359 enc_16lsd::<{ u128::MAX_STR_LEN - 32 }>(buf, mod2);
361 (quot2 as u64, u128::MAX_STR_LEN - 32)
363 }
364 };
365
366 while remain > 999 {
368 offset -= 4;
369
370 let quad = remain % 1_00_00;
372 remain /= 1_00_00;
373 let (pair1, pair2) = divmod100(quad as u32);
374 unsafe {
375 buf[offset + 0].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 + 0));
376 buf[offset + 1].write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 + 1));
377 buf[offset + 2].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 + 0));
378 buf[offset + 3].write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 + 1));
379 }
380 }
381
382 if remain > 9 {
384 offset -= 2;
385
386 let (last, pair) = divmod100(remain as u32);
387 remain = last as u64;
388 unsafe {
389 buf[offset + 0].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 + 0));
390 buf[offset + 1].write(*DECIMAL_PAIRS.0.get_unchecked(pair as usize * 2 + 1));
391 }
392 }
393
394 if remain != 0 {
396 offset -= 1;
397
398 let last = remain as u8 & 15;
401 buf[offset].write(b'0' + last);
402 }
404 offset
405 }
406}
407
408#[cfg_attr(feature = "no-panic", no_panic)]
410fn enc_16lsd<const OFFSET: usize>(buf: &mut [MaybeUninit<u8>], n: u64) {
411 let mut remain = n;
413
414 for quad_index in (0..4).rev() {
416 let quad = remain % 1_00_00;
418 remain /= 1_00_00;
419 let (pair1, pair2) = divmod100(quad as u32);
420 unsafe {
421 buf[quad_index * 4 + OFFSET + 0]
422 .write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 + 0));
423 buf[quad_index * 4 + OFFSET + 1]
424 .write(*DECIMAL_PAIRS.0.get_unchecked(pair1 as usize * 2 + 1));
425 buf[quad_index * 4 + OFFSET + 2]
426 .write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 + 0));
427 buf[quad_index * 4 + OFFSET + 3]
428 .write(*DECIMAL_PAIRS.0.get_unchecked(pair2 as usize * 2 + 1));
429 }
430 }
431}
432
433#[cfg_attr(feature = "no-panic", no_panic)]
443fn div_rem_1e16(n: u128) -> (u128, u64) {
444 const D: u128 = 1_0000_0000_0000_0000;
445 if n < D {
447 return (0, n as u64);
448 }
449
450 const M_HIGH: u128 = 76624777043294442917917351357515459181;
453 const SH_POST: u8 = 51;
454
455 let quot = u128_ext::mulhi(n, M_HIGH) >> SH_POST;
457 let rem = n - quot * D;
458 (quot, rem as u64)
459}