1#![doc(html_root_url = "https://docs.rs/itoa/1.0.15")]
33#![no_std]
34#![allow(
35 clippy::cast_lossless,
36 clippy::cast_possible_truncation,
37 clippy::cast_possible_wrap,
38 clippy::cast_sign_loss,
39 clippy::expl_impl_clone_on_copy,
40 clippy::must_use_candidate,
41 clippy::needless_doctest_main,
42 clippy::unreadable_literal
43)]
44
45mod udiv128;
46
47use core::hint;
48use core::mem::MaybeUninit;
49use core::{ptr, slice, str};
50#[cfg(feature = "no-panic")]
51use no_panic::no_panic;
52
53pub struct Buffer {
64 bytes: [MaybeUninit<u8>; i128::MAX_STR_LEN],
65}
66
67impl Default for Buffer {
68 #[inline]
69 fn default() -> Buffer {
70 Buffer::new()
71 }
72}
73
74impl Copy for Buffer {}
75
76#[allow(clippy::non_canonical_clone_impl)]
77impl Clone for Buffer {
78 #[inline]
79 fn clone(&self) -> Self {
80 Buffer::new()
81 }
82}
83
84impl Buffer {
85 #[inline]
88 #[cfg_attr(feature = "no-panic", no_panic)]
89 pub const fn new() -> Buffer {
90 let bytes = [MaybeUninit::<u8>::uninit(); i128::MAX_STR_LEN];
91 Buffer { bytes }
92 }
93
94 #[cfg_attr(feature = "no-panic", no_panic)]
97 pub fn format<I: Integer>(&mut self, i: I) -> &str {
98 #[expect(clippy::ptr_as_ptr)]
99 #[expect(clippy::borrow_as_ptr)]
100 let string = i.write(unsafe {
101 &mut *(&mut self.bytes as *mut [MaybeUninit<u8>; i128::MAX_STR_LEN]
102 as *mut <I as private::Sealed>::Buffer)
103 });
104 if string.len() > I::MAX_STR_LEN {
105 unsafe { hint::unreachable_unchecked() };
106 }
107 string
108 }
109}
110
111pub trait Integer: private::Sealed {
115 const MAX_STR_LEN: usize;
118}
119
120struct ConstInteger<T>(T);
122
123mod private {
125 #[doc(hidden)]
126 pub trait Sealed: Copy {
127 #[doc(hidden)]
128 type Buffer: 'static;
129 fn write(self, buf: &mut Self::Buffer) -> &str;
130 }
131}
132
133const DEC_DIGITS_LUT: [u8; 200] = *b"\
134 0001020304050607080910111213141516171819\
135 2021222324252627282930313233343536373839\
136 4041424344454647484950515253545556575859\
137 6061626364656667686970717273747576777879\
138 8081828384858687888990919293949596979899";
139
140macro_rules! impl_Integer {
143 ($t:ty[len = $max_len:expr] as $large_unsigned:ty) => {
144 impl Integer for $t {
145 const MAX_STR_LEN: usize = $max_len;
146 }
147
148 impl private::Sealed for $t {
149 type Buffer = [MaybeUninit<u8>; $max_len];
150
151 #[inline]
152 #[cfg_attr(feature = "no-panic", no_panic)]
153 fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
154 ConstInteger(self).write(buf)
155 }
156 }
157
158 impl ConstInteger<$t> {
159 #[allow(unused_comparisons)]
160 #[inline]
161 pub const fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
162 let Self(this) = self;
163 let is_nonnegative = this >= 0;
164 let mut n = if is_nonnegative {
165 this as $large_unsigned
166 } else {
167 (!(this as $large_unsigned)).wrapping_add(1)
169 };
170 let mut curr = buf.len();
171 #[expect(clippy::ptr_as_ptr)]
172 let buf_ptr = buf.as_mut_ptr() as *mut u8;
173 let lut_ptr = DEC_DIGITS_LUT.as_ptr();
174
175 while n >= 10000 {
177 let rem = n % 10000;
178 n /= 10000;
179
180 let d1 = ((rem / 100) << 1) as usize;
181 let d2 = ((rem % 100) << 1) as usize;
182 curr -= 4;
183 unsafe {
184 ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
185 ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2);
186 }
187 }
188
189 if n >= 100 {
191 let d1 = ((n % 100) << 1) as usize;
192 n /= 100;
193 curr -= 2;
194 unsafe {
195 ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
196 }
197 }
198
199 if n < 10 {
201 curr -= 1;
202 unsafe {
203 *buf_ptr.add(curr) = (n as u8) + b'0';
204 }
205 } else {
206 let d1 = (n << 1) as usize;
207 curr -= 2;
208 unsafe {
209 ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
210 }
211 }
212
213 if !is_nonnegative {
214 curr -= 1;
215 unsafe {
216 *buf_ptr.add(curr) = b'-';
217 }
218 }
219
220 let len = buf.len() - curr;
221 let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
222 unsafe { str::from_utf8_unchecked(bytes) }
223 }
224 }
225 };
226}
227
228impl Integer for i8 {
const MAX_STR_LEN: usize = 4;
}
impl private::Sealed for i8 {
type Buffer = [MaybeUninit<u8>; 4];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 4]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<i8> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 4]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u32
} else { (!(this as u32)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(i8[len = 4] as u32);
229impl Integer for u8 {
const MAX_STR_LEN: usize = 3;
}
impl private::Sealed for u8 {
type Buffer = [MaybeUninit<u8>; 3];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 3]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<u8> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 3]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u32
} else { (!(this as u32)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(u8[len = 3] as u32);
230impl Integer for i16 {
const MAX_STR_LEN: usize = 6;
}
impl private::Sealed for i16 {
type Buffer = [MaybeUninit<u8>; 6];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 6]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<i16> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 6]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u32
} else { (!(this as u32)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(i16[len = 6] as u32);
231impl Integer for u16 {
const MAX_STR_LEN: usize = 5;
}
impl private::Sealed for u16 {
type Buffer = [MaybeUninit<u8>; 5];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 5]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<u16> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 5]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u32
} else { (!(this as u32)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(u16[len = 5] as u32);
232impl Integer for i32 {
const MAX_STR_LEN: usize = 11;
}
impl private::Sealed for i32 {
type Buffer = [MaybeUninit<u8>; 11];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 11]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<i32> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 11]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u32
} else { (!(this as u32)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(i32[len = 11] as u32);
233impl Integer for u32 {
const MAX_STR_LEN: usize = 10;
}
impl private::Sealed for u32 {
type Buffer = [MaybeUninit<u8>; 10];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 10]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<u32> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 10]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u32
} else { (!(this as u32)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(u32[len = 10] as u32);
234impl Integer for i64 {
const MAX_STR_LEN: usize = 20;
}
impl private::Sealed for i64 {
type Buffer = [MaybeUninit<u8>; 20];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 20]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<i64> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 20]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u64
} else { (!(this as u64)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(i64[len = 20] as u64);
235impl Integer for u64 {
const MAX_STR_LEN: usize = 20;
}
impl private::Sealed for u64 {
type Buffer = [MaybeUninit<u8>; 20];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 20]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<u64> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 20]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let mut n =
if is_nonnegative {
this as u64
} else { (!(this as u64)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
while n >= 10000 {
let rem = n % 10000;
n /= 10000;
let d1 = ((rem / 100) << 1) as usize;
let d2 = ((rem % 100) << 1) as usize;
curr -= 4;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
ptr::copy_nonoverlapping(lut_ptr.add(d2),
buf_ptr.add(curr + 2), 2);
}
}
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if n < 10 {
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
} else {
let d1 = (n << 1) as usize;
curr -= 2;
unsafe {
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr),
2);
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer!(u64[len = 20] as u64);
236
237macro_rules! impl_Integer_size {
238 ($t:ty as $primitive:ident #[cfg(target_pointer_width = $width:literal)]) => {
239 #[cfg(target_pointer_width = $width)]
240 impl Integer for $t {
241 const MAX_STR_LEN: usize = <$primitive as Integer>::MAX_STR_LEN;
242 }
243
244 #[cfg(target_pointer_width = $width)]
245 impl private::Sealed for $t {
246 type Buffer = <$primitive as private::Sealed>::Buffer;
247
248 #[inline]
249 #[cfg_attr(feature = "no-panic", no_panic)]
250 fn write(self, buf: &mut Self::Buffer) -> &str {
251 (self as $primitive).write(buf)
252 }
253 }
254
255 #[cfg(target_pointer_width = $width)]
256 impl ConstInteger<$t> {
257 #[inline]
258 const fn write(
259 self,
260 buf: &mut [MaybeUninit<u8>; <$t as Integer>::MAX_STR_LEN],
261 ) -> &str {
262 ConstInteger(self.0 as $primitive).write(buf)
263 }
264 }
265 };
266}
267
268impl_Integer_size!(isize as i16 #[cfg(target_pointer_width = "16")]);
269impl_Integer_size!(usize as u16 #[cfg(target_pointer_width = "16")]);
270impl_Integer_size!(isize as i32 #[cfg(target_pointer_width = "32")]);
271impl_Integer_size!(usize as u32 #[cfg(target_pointer_width = "32")]);
272impl 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 ConstInteger<isize> {
#[inline]
const fn write(self,
buf: &mut [MaybeUninit<u8>; <isize as Integer>::MAX_STR_LEN])
-> &str {
ConstInteger(self.0 as i64).write(buf)
}
}impl_Integer_size!(isize as i64 #[cfg(target_pointer_width = "64")]);
273impl 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 ConstInteger<usize> {
#[inline]
const fn write(self,
buf: &mut [MaybeUninit<u8>; <usize as Integer>::MAX_STR_LEN])
-> &str {
ConstInteger(self.0 as u64).write(buf)
}
}impl_Integer_size!(usize as u64 #[cfg(target_pointer_width = "64")]);
274
275macro_rules! impl_Integer128 {
276 ($t:ty[len = $max_len:expr]) => {
277 impl Integer for $t {
278 const MAX_STR_LEN: usize = $max_len;
279 }
280
281 impl private::Sealed for $t {
282 type Buffer = [MaybeUninit<u8>; $max_len];
283
284 #[inline]
285 #[cfg_attr(feature = "no-panic", no_panic)]
286 fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
287 ConstInteger(self).write(buf)
288 }
289 }
290
291 impl ConstInteger<$t> {
292 #[allow(unused_comparisons)]
293 #[inline]
294 #[cfg_attr(feature = "no-panic", no_panic)]
295 pub const fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
296 let Self(this) = self;
297 let is_nonnegative = this >= 0;
298 let n = if is_nonnegative {
299 this as u128
300 } else {
301 (!(this as u128)).wrapping_add(1)
303 };
304 let mut curr = buf.len();
305 #[expect(clippy::ptr_as_ptr)]
306 let buf_ptr = buf.as_mut_ptr() as *mut u8;
307
308 let (n, rem) = udiv128::udivmod_1e19(n);
310 #[expect(clippy::ptr_as_ptr)]
311 let buf1 = unsafe {
312 buf_ptr.add(curr - u64::MAX_STR_LEN) as *mut [MaybeUninit<u8>; u64::MAX_STR_LEN]
313 };
314 curr -= ConstInteger(rem).write(unsafe { &mut *buf1 }).len();
315
316 if n != 0 {
317 let target = buf.len() - 19;
319 unsafe {
320 ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
321 }
322 curr = target;
323
324 let (n, rem) = udiv128::udivmod_1e19(n);
326 #[expect(clippy::ptr_as_ptr)]
327 let buf2 = unsafe {
328 buf_ptr.add(curr - u64::MAX_STR_LEN)
329 as *mut [MaybeUninit<u8>; u64::MAX_STR_LEN]
330 };
331 curr -= ConstInteger(rem).write(unsafe { &mut *buf2 }).len();
332
333 if n != 0 {
334 let target = buf.len() - 38;
336 unsafe {
337 ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
338 }
339 curr = target;
340
341 curr -= 1;
344 unsafe {
345 *buf_ptr.add(curr) = (n as u8) + b'0';
346 }
347 }
348 }
349
350 if !is_nonnegative {
351 curr -= 1;
352 unsafe {
353 *buf_ptr.add(curr) = b'-';
354 }
355 }
356
357 let len = buf.len() - curr;
358 let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
359 unsafe { str::from_utf8_unchecked(bytes) }
360 }
361 }
362 };
363}
364
365impl Integer for i128 {
const MAX_STR_LEN: usize = 40;
}
impl private::Sealed for i128 {
type Buffer = [MaybeUninit<u8>; 40];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 40]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<i128> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 40]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let n =
if is_nonnegative {
this as u128
} else { (!(this as u128)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let (n, rem) = udiv128::udivmod_1e19(n);
#[expect(clippy :: ptr_as_ptr)]
let buf1 =
unsafe {
buf_ptr.add(curr - u64::MAX_STR_LEN) as
*mut [MaybeUninit<u8>; u64::MAX_STR_LEN]
};
curr -= ConstInteger(rem).write(unsafe { &mut *buf1 }).len();
if n != 0 {
let target = buf.len() - 19;
unsafe {
ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
}
curr = target;
let (n, rem) = udiv128::udivmod_1e19(n);
#[expect(clippy :: ptr_as_ptr)]
let buf2 =
unsafe {
buf_ptr.add(curr - u64::MAX_STR_LEN) as
*mut [MaybeUninit<u8>; u64::MAX_STR_LEN]
};
curr -= ConstInteger(rem).write(unsafe { &mut *buf2 }).len();
if n != 0 {
let target = buf.len() - 38;
unsafe {
ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
}
curr = target;
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer128!(i128[len = 40]);
366impl Integer for u128 {
const MAX_STR_LEN: usize = 39;
}
impl private::Sealed for u128 {
type Buffer = [MaybeUninit<u8>; 39];
#[inline]
fn write(self, buf: &mut [MaybeUninit<u8>; 39]) -> &str {
ConstInteger(self).write(buf)
}
}
impl ConstInteger<u128> {
#[allow(unused_comparisons)]
#[inline]
pub const fn write(self, buf: &mut [MaybeUninit<u8>; 39]) -> &str {
let Self(this) = self;
let is_nonnegative = this >= 0;
let n =
if is_nonnegative {
this as u128
} else { (!(this as u128)).wrapping_add(1) };
let mut curr = buf.len();
#[expect(clippy :: ptr_as_ptr)]
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let (n, rem) = udiv128::udivmod_1e19(n);
#[expect(clippy :: ptr_as_ptr)]
let buf1 =
unsafe {
buf_ptr.add(curr - u64::MAX_STR_LEN) as
*mut [MaybeUninit<u8>; u64::MAX_STR_LEN]
};
curr -= ConstInteger(rem).write(unsafe { &mut *buf1 }).len();
if n != 0 {
let target = buf.len() - 19;
unsafe {
ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
}
curr = target;
let (n, rem) = udiv128::udivmod_1e19(n);
#[expect(clippy :: ptr_as_ptr)]
let buf2 =
unsafe {
buf_ptr.add(curr - u64::MAX_STR_LEN) as
*mut [MaybeUninit<u8>; u64::MAX_STR_LEN]
};
curr -= ConstInteger(rem).write(unsafe { &mut *buf2 }).len();
if n != 0 {
let target = buf.len() - 38;
unsafe {
ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
}
curr = target;
curr -= 1;
unsafe { *buf_ptr.add(curr) = (n as u8) + b'0'; }
}
}
if !is_nonnegative {
curr -= 1;
unsafe { *buf_ptr.add(curr) = b'-'; }
}
let len = buf.len() - curr;
let bytes = unsafe { slice::from_raw_parts(buf_ptr.add(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}impl_Integer128!(u128[len = 39]);
367
368pub struct Format<'a, B, T>(pub &'a mut B, pub T);
386
387macro_rules! impl_fns {
388 (
389 type $T:ident = each_of!$each_of:tt;
390
391 $($rest:tt)*
392 ) => {
393 impl_fns! { @impl $T $each_of {$($rest)*} }
394 };
395 (@impl $T:ident [$($Ty:ty),* $(,)?] $impl_body:tt) => {$(
396 const _: () = {
397 type $T = $Ty;
398 const _: () = $impl_body;
399 };
400 )*};
401}
402const _: () =
{
type I = u128;
const _: () =
{
impl<'a>
Format<'a, [MaybeUninit<u8>; <I as Integer>::MAX_STR_LEN],
I> {
pub const fn call_once(self) -> &'a str {
let Self(buf, i) = self;
ConstInteger(i).write(buf)
}
}
impl<'a> Format<'a, Buffer, I> {
#[doc = r" Const version of [`Buffer::format()`]."]
pub const fn call_once(self) -> &'a str {
let Self(buf, i) = self;
let i = ConstInteger(i);
#[expect(clippy::ptr_as_ptr)]
#[expect(clippy::borrow_as_ptr)]
let string =
i.write(unsafe {
&mut *(&mut buf.bytes as
*mut [MaybeUninit<u8>; i128::MAX_STR_LEN] as
*mut <I as private::Sealed>::Buffer)
});
if string.len() > I::MAX_STR_LEN {
unsafe { hint::unreachable_unchecked() };
}
string
}
}
};
};impl_fns!(
403 type I = each_of![
404 i8, u8, i16, u16, i32, u32, i64, u64, isize, usize, i128, u128, ];
408
409 impl<'a> Format<'a, [MaybeUninit<u8>; <I as Integer>::MAX_STR_LEN], I> {
410 pub const fn call_once(self) -> &'a str {
411 let Self(buf, i) = self;
412
413 ConstInteger(i).write(buf)
414 }
415 }
416
417 impl<'a> Format<'a, Buffer, I> {
418 pub const fn call_once(self) -> &'a str {
420 let Self(buf, i) = self;
421 let i = ConstInteger(i);
422
423 #[expect(clippy::ptr_as_ptr)]
424 #[expect(clippy::borrow_as_ptr)]
425 let string = i.write(unsafe {
426 &mut *(&mut buf.bytes as *mut [MaybeUninit<u8>; i128::MAX_STR_LEN]
427 as *mut <I as private::Sealed>::Buffer)
428 });
429 if string.len() > I::MAX_STR_LEN {
430 unsafe { hint::unreachable_unchecked() };
431 }
432 string
433 }
434 }
435);