xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/itoa-1.0.11/src/lib.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 //! [![github]](https://github.com/dtolnay/itoa) [![crates-io]](https://crates.io/crates/itoa) [![docs-rs]](https://docs.rs/itoa)
2 //!
3 //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4 //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5 //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6 //!
7 //! <br>
8 //!
9 //! This crate provides a fast conversion of integer primitives to decimal
10 //! strings. The implementation comes straight from [libcore] but avoids the
11 //! performance penalty of going through [`core::fmt::Formatter`].
12 //!
13 //! See also [`ryu`] for printing floating point primitives.
14 //!
15 //! [libcore]: https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254
16 //! [`core::fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html
17 //! [`ryu`]: https://github.com/dtolnay/ryu
18 //!
19 //! # Example
20 //!
21 //! ```
22 //! fn main() {
23 //!     let mut buffer = itoa::Buffer::new();
24 //!     let printed = buffer.format(128u64);
25 //!     assert_eq!(printed, "128");
26 //! }
27 //! ```
28 //!
29 //! # Performance (lower is better)
30 //!
31 //! ![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png)
32 
33 #![doc(html_root_url = "https://docs.rs/itoa/1.0.11")]
34 #![no_std]
35 #![allow(
36     clippy::cast_lossless,
37     clippy::cast_possible_truncation,
38     clippy::expl_impl_clone_on_copy,
39     clippy::must_use_candidate,
40     clippy::needless_doctest_main,
41     clippy::unreadable_literal
42 )]
43 
44 mod udiv128;
45 
46 use core::mem::{self, MaybeUninit};
47 use core::{ptr, slice, str};
48 #[cfg(feature = "no-panic")]
49 use no_panic::no_panic;
50 
51 /// A correctly sized stack allocation for the formatted integer to be written
52 /// into.
53 ///
54 /// # Example
55 ///
56 /// ```
57 /// let mut buffer = itoa::Buffer::new();
58 /// let printed = buffer.format(1234);
59 /// assert_eq!(printed, "1234");
60 /// ```
61 pub struct Buffer {
62     bytes: [MaybeUninit<u8>; I128_MAX_LEN],
63 }
64 
65 impl Default for Buffer {
66     #[inline]
default() -> Buffer67     fn default() -> Buffer {
68         Buffer::new()
69     }
70 }
71 
72 impl Copy for Buffer {}
73 
74 impl Clone for Buffer {
75     #[inline]
76     #[allow(clippy::non_canonical_clone_impl)] // false positive https://github.com/rust-lang/rust-clippy/issues/11072
clone(&self) -> Self77     fn clone(&self) -> Self {
78         Buffer::new()
79     }
80 }
81 
82 impl Buffer {
83     /// This is a cheap operation; you don't need to worry about reusing buffers
84     /// for efficiency.
85     #[inline]
86     #[cfg_attr(feature = "no-panic", no_panic)]
new() -> Buffer87     pub fn new() -> Buffer {
88         let bytes = [MaybeUninit::<u8>::uninit(); I128_MAX_LEN];
89         Buffer { bytes }
90     }
91 
92     /// Print an integer into this buffer and return a reference to its string
93     /// representation within the buffer.
94     #[cfg_attr(feature = "no-panic", no_panic)]
format<I: Integer>(&mut self, i: I) -> &str95     pub fn format<I: Integer>(&mut self, i: I) -> &str {
96         i.write(unsafe {
97             &mut *(&mut self.bytes as *mut [MaybeUninit<u8>; I128_MAX_LEN]
98                 as *mut <I as private::Sealed>::Buffer)
99         })
100     }
101 }
102 
103 /// An integer that can be written into an [`itoa::Buffer`][Buffer].
104 ///
105 /// This trait is sealed and cannot be implemented for types outside of itoa.
106 pub trait Integer: private::Sealed {}
107 
108 // Seal to prevent downstream implementations of the Integer trait.
109 mod private {
110     pub trait Sealed: Copy {
111         type Buffer: 'static;
write(self, buf: &mut Self::Buffer) -> &str112         fn write(self, buf: &mut Self::Buffer) -> &str;
113     }
114 }
115 
116 const DEC_DIGITS_LUT: &[u8] = b"\
117       0001020304050607080910111213141516171819\
118       2021222324252627282930313233343536373839\
119       4041424344454647484950515253545556575859\
120       6061626364656667686970717273747576777879\
121       8081828384858687888990919293949596979899";
122 
123 // Adaptation of the original implementation at
124 // https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
125 macro_rules! impl_Integer {
126     ($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
127         impl Integer for $t {}
128 
129         impl private::Sealed for $t {
130             type Buffer = [MaybeUninit<u8>; $max_len];
131 
132             #[allow(unused_comparisons)]
133             #[inline]
134             #[cfg_attr(feature = "no-panic", no_panic)]
135             fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
136                 let is_nonnegative = self >= 0;
137                 let mut n = if is_nonnegative {
138                     self as $conv_fn
139                 } else {
140                     // Convert negative number to positive by summing 1 to its two's complement.
141                     (!(self as $conv_fn)).wrapping_add(1)
142                 };
143                 let mut curr = buf.len() as isize;
144                 let buf_ptr = buf.as_mut_ptr() as *mut u8;
145                 let lut_ptr = DEC_DIGITS_LUT.as_ptr();
146 
147                 // Need at least 16 bits for the 4-digits-at-a-time to work.
148                 if mem::size_of::<$t>() >= 2 {
149                     // Eagerly decode 4 digits at a time.
150                     while n >= 10000 {
151                         let rem = (n % 10000) as isize;
152                         n /= 10000;
153 
154                         let d1 = (rem / 100) << 1;
155                         let d2 = (rem % 100) << 1;
156                         curr -= 4;
157                         unsafe {
158                             ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
159                             ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
160                         }
161                     }
162                 }
163 
164                 // If we reach here, numbers are <=9999 so at most 4 digits long.
165                 let mut n = n as isize; // Possibly reduce 64-bit math.
166 
167                 // Decode 2 more digits, if >2 digits.
168                 if n >= 100 {
169                     let d1 = (n % 100) << 1;
170                     n /= 100;
171                     curr -= 2;
172                     unsafe {
173                         ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
174                     }
175                 }
176 
177                 // Decode last 1 or 2 digits.
178                 if n < 10 {
179                     curr -= 1;
180                     unsafe {
181                         *buf_ptr.offset(curr) = (n as u8) + b'0';
182                     }
183                 } else {
184                     let d1 = n << 1;
185                     curr -= 2;
186                     unsafe {
187                         ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
188                     }
189                 }
190 
191                 if !is_nonnegative {
192                     curr -= 1;
193                     unsafe {
194                         *buf_ptr.offset(curr) = b'-';
195                     }
196                 }
197 
198                 let len = buf.len() - curr as usize;
199                 let bytes = unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) };
200                 unsafe { str::from_utf8_unchecked(bytes) }
201             }
202         }
203     )*};
204 }
205 
206 const I8_MAX_LEN: usize = 4;
207 const U8_MAX_LEN: usize = 3;
208 const I16_MAX_LEN: usize = 6;
209 const U16_MAX_LEN: usize = 5;
210 const I32_MAX_LEN: usize = 11;
211 const U32_MAX_LEN: usize = 10;
212 const I64_MAX_LEN: usize = 20;
213 const U64_MAX_LEN: usize = 20;
214 
215 impl_Integer!(
216     I8_MAX_LEN => i8,
217     U8_MAX_LEN => u8,
218     I16_MAX_LEN => i16,
219     U16_MAX_LEN => u16,
220     I32_MAX_LEN => i32,
221     U32_MAX_LEN => u32
222     as u32);
223 
224 impl_Integer!(I64_MAX_LEN => i64, U64_MAX_LEN => u64 as u64);
225 
226 #[cfg(target_pointer_width = "16")]
227 impl_Integer!(I16_MAX_LEN => isize, U16_MAX_LEN => usize as u16);
228 
229 #[cfg(target_pointer_width = "32")]
230 impl_Integer!(I32_MAX_LEN => isize, U32_MAX_LEN => usize as u32);
231 
232 #[cfg(target_pointer_width = "64")]
233 impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64);
234 
235 macro_rules! impl_Integer128 {
236     ($($max_len:expr => $t:ident),*) => {$(
237         impl Integer for $t {}
238 
239         impl private::Sealed for $t {
240             type Buffer = [MaybeUninit<u8>; $max_len];
241 
242             #[allow(unused_comparisons)]
243             #[inline]
244             #[cfg_attr(feature = "no-panic", no_panic)]
245             fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
246                 let is_nonnegative = self >= 0;
247                 let n = if is_nonnegative {
248                     self as u128
249                 } else {
250                     // Convert negative number to positive by summing 1 to its two's complement.
251                     (!(self as u128)).wrapping_add(1)
252                 };
253                 let mut curr = buf.len() as isize;
254                 let buf_ptr = buf.as_mut_ptr() as *mut u8;
255 
256                 // Divide by 10^19 which is the highest power less than 2^64.
257                 let (n, rem) = udiv128::udivmod_1e19(n);
258                 let buf1 = unsafe { buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [MaybeUninit<u8>; U64_MAX_LEN] };
259                 curr -= rem.write(unsafe { &mut *buf1 }).len() as isize;
260 
261                 if n != 0 {
262                     // Memset the base10 leading zeros of rem.
263                     let target = buf.len() as isize - 19;
264                     unsafe {
265                         ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
266                     }
267                     curr = target;
268 
269                     // Divide by 10^19 again.
270                     let (n, rem) = udiv128::udivmod_1e19(n);
271                     let buf2 = unsafe { buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [MaybeUninit<u8>; U64_MAX_LEN] };
272                     curr -= rem.write(unsafe { &mut *buf2 }).len() as isize;
273 
274                     if n != 0 {
275                         // Memset the leading zeros.
276                         let target = buf.len() as isize - 38;
277                         unsafe {
278                             ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
279                         }
280                         curr = target;
281 
282                         // There is at most one digit left
283                         // because u128::MAX / 10^19 / 10^19 is 3.
284                         curr -= 1;
285                         unsafe {
286                             *buf_ptr.offset(curr) = (n as u8) + b'0';
287                         }
288                     }
289                 }
290 
291                 if !is_nonnegative {
292                     curr -= 1;
293                     unsafe {
294                         *buf_ptr.offset(curr) = b'-';
295                     }
296                 }
297 
298                 let len = buf.len() - curr as usize;
299                 let bytes = unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) };
300                 unsafe { str::from_utf8_unchecked(bytes) }
301             }
302         }
303     )*};
304 }
305 
306 const U128_MAX_LEN: usize = 39;
307 const I128_MAX_LEN: usize = 40;
308 
309 impl_Integer128!(I128_MAX_LEN => i128, U128_MAX_LEN => u128);
310