1use super::*;
2use core::num::NonZero;
3
4pub(super) trait NumToRepr {
5 fn into_repr(self) -> Result<Repr, ReserveError>;
6}
7
8impl NumToRepr for f32 {
9 #[inline]
10 fn into_repr(self) -> Result<Repr, ReserveError> {
11 Repr::from_str(ryu::Buffer::new().format(self))
12 }
13}
14
15impl NumToRepr for f64 {
16 #[inline]
17 fn into_repr(self) -> Result<Repr, ReserveError> {
18 Repr::from_str(ryu::Buffer::new().format(self))
19 }
20}
21
22impl NumToRepr for u128 {
23 #[inline]
24 fn into_repr(self) -> Result<Repr, ReserveError> {
25 Repr::from_str(itoa::Buffer::new().format(self))
26 }
27}
28
29impl NumToRepr for i128 {
30 #[inline]
31 fn into_repr(self) -> Result<Repr, ReserveError> {
32 Repr::from_str(itoa::Buffer::new().format(self))
33 }
34}
35
36const DEC_DIGITS_LUT: &[u8; 200] = b"\
41 0001020304050607080910111213141516171819\
42 2021222324252627282930313233343536373839\
43 4041424344454647484950515253545556575859\
44 6061626364656667686970717273747576777879\
45 8081828384858687888990919293949596979899";
46
47macro_rules! impl_NumToRepr_for_integers {
48 ($($t:ty),* ; as $u:ty) => {$(
49 impl NumToRepr for $t {
50 fn into_repr(self) -> Result<Repr, ReserveError> {
51 let digits_count = DigitCount::digit_count(self);
52
53 #[allow(unused_comparisons)]
54 let is_nonnegative = self >= 0;
55 let mut n = if is_nonnegative {
56 self as $u
57 } else {
58 (!(self as $u)).wrapping_add(1)
61 };
62
63 let mut repr = Repr::with_capacity(digits_count)?;
64
65 let buf_ptr = unsafe { repr.as_slice_mut().as_mut_ptr() };
68
69 let lut_ptr = DEC_DIGITS_LUT.as_ptr();
70 let mut curr = digits_count;
71
72 unsafe {
78 if size_of::<$t>() >= 2 {
83 while n >= 10000 {
85 let rem = (n % 10000) as usize;
86 n /= 10000;
87
88 let d1 = (rem / 100) << 1;
89 let d2 = (rem % 100) << 1;
90 curr -= 4;
91
92 ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
96 ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2);
97 }
98 }
99
100 let mut n = n as usize;
102
103 if n >= 100 {
105 let d1 = (n % 100) << 1;
106 n /= 100;
107 curr -= 2;
108 ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
109 }
110
111 if n < 10 {
115 curr -= 1;
116 *buf_ptr.add(curr) = (n as u8) + b'0';
117 } else {
118 let d1 = n << 1;
119 curr -= 2;
120 ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
121 }
122
123 if !is_nonnegative {
124 curr -= 1;
125 *buf_ptr.add(curr) = b'-';
126 }
127
128 repr.set_len(digits_count);
129 }
130
131 debug_assert_eq!(curr, 0);
132
133 Ok(repr)
134 }
135 }
136 )*};
137}
138
139#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
140impl_NumToRepr_for_integers!(
141 i8, u8, i16, u16, i32, u32, isize, usize;
142 as u64
143);
144
145#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
146impl_NumToRepr_for_integers!(
147 i8, u8, i16, u16, i32, u32, isize, usize;
148 as u32
149);
150
151impl_NumToRepr_for_integers!(
152 i64, u64;
153 as u64
154);
155
156macro_rules! impl_IntoRepr_for_nonzero_integers {
158 ($($itype:ty),* $(,)?) => {$(
159 impl NumToRepr for $itype {
160 #[inline]
161 fn into_repr(self) -> Result<Repr, ReserveError> {
162 self.get().into_repr()
163 }
164 }
165 )*};
166}
167impl_IntoRepr_for_nonzero_integers!(
168 NonZero<i8>,
169 NonZero<u8>,
170 NonZero<i16>,
171 NonZero<u16>,
172 NonZero<i32>,
173 NonZero<u32>,
174 NonZero<i64>,
175 NonZero<u64>,
176 NonZero<i128>,
177 NonZero<u128>,
178 NonZero<isize>,
179 NonZero<usize>,
180);
181
182trait DigitCount {
183 fn digit_count(self) -> usize;
184}
185
186impl DigitCount for u8 {
187 #[inline(always)]
188 fn digit_count(self) -> usize {
189 match self {
190 u8::MIN..=9 => 1,
191 10..=99 => 2,
192 100..=u8::MAX => 3,
193 }
194 }
195}
196
197impl DigitCount for i8 {
198 #[inline(always)]
199 fn digit_count(self) -> usize {
200 match self {
201 i8::MIN..=-100 => 4,
202 -99..=-10 => 3,
203 -9..=-1 => 2,
204 0..=9 => 1,
205 10..=99 => 2,
206 100..=i8::MAX => 3,
207 }
208 }
209}
210
211impl DigitCount for u16 {
212 #[inline(always)]
213 fn digit_count(self) -> usize {
214 match self {
215 u16::MIN..=9 => 1,
216 10..=99 => 2,
217 100..=999 => 3,
218 1000..=9999 => 4,
219 10000..=u16::MAX => 5,
220 }
221 }
222}
223
224impl DigitCount for i16 {
225 #[inline(always)]
226 fn digit_count(self) -> usize {
227 match self {
228 i16::MIN..=-10000 => 6,
229 -9999..=-1000 => 5,
230 -999..=-100 => 4,
231 -99..=-10 => 3,
232 -9..=-1 => 2,
233 0..=9 => 1,
234 10..=99 => 2,
235 100..=999 => 3,
236 1000..=9999 => 4,
237 10000..=i16::MAX => 5,
238 }
239 }
240}
241
242impl DigitCount for u32 {
243 #[inline(always)]
244 fn digit_count(self) -> usize {
245 match self {
246 u32::MIN..=9 => 1,
247 10..=99 => 2,
248 100..=999 => 3,
249 1000..=9999 => 4,
250 10000..=99999 => 5,
251 100000..=999999 => 6,
252 1000000..=9999999 => 7,
253 10000000..=99999999 => 8,
254 100000000..=999999999 => 9,
255 1000000000..=u32::MAX => 10,
256 }
257 }
258}
259
260impl DigitCount for i32 {
261 #[inline(always)]
262 fn digit_count(self) -> usize {
263 match self {
264 i32::MIN..=-1000000000 => 11,
265 -999999999..=-100000000 => 10,
266 -99999999..=-10000000 => 9,
267 -9999999..=-1000000 => 8,
268 -999999..=-100000 => 7,
269 -99999..=-10000 => 6,
270 -9999..=-1000 => 5,
271 -999..=-100 => 4,
272 -99..=-10 => 3,
273 -9..=-1 => 2,
274 0..=9 => 1,
275 10..=99 => 2,
276 100..=999 => 3,
277 1000..=9999 => 4,
278 10000..=99999 => 5,
279 100000..=999999 => 6,
280 1000000..=9999999 => 7,
281 10000000..=99999999 => 8,
282 100000000..=999999999 => 9,
283 1000000000..=i32::MAX => 10,
284 }
285 }
286}
287
288impl DigitCount for u64 {
289 #[inline(always)]
290 fn digit_count(self) -> usize {
291 match self {
292 u64::MIN..=9 => 1,
293 10..=99 => 2,
294 100..=999 => 3,
295 1000..=9999 => 4,
296 10000..=99999 => 5,
297 100000..=999999 => 6,
298 1000000..=9999999 => 7,
299 10000000..=99999999 => 8,
300 100000000..=999999999 => 9,
301 1000000000..=9999999999 => 10,
302 10000000000..=99999999999 => 11,
303 100000000000..=999999999999 => 12,
304 1000000000000..=9999999999999 => 13,
305 10000000000000..=99999999999999 => 14,
306 100000000000000..=999999999999999 => 15,
307 1000000000000000..=9999999999999999 => 16,
308 10000000000000000..=99999999999999999 => 17,
309 100000000000000000..=999999999999999999 => 18,
310 1000000000000000000..=9999999999999999999 => 19,
311 10000000000000000000..=u64::MAX => 20,
312 }
313 }
314}
315
316impl DigitCount for i64 {
317 #[inline(always)]
318 fn digit_count(self) -> usize {
319 match self {
320 i64::MIN..=-1000000000000000000 => 20,
321 -999999999999999999..=-100000000000000000 => 19,
322 -99999999999999999..=-10000000000000000 => 18,
323 -9999999999999999..=-1000000000000000 => 17,
324 -999999999999999..=-100000000000000 => 16,
325 -99999999999999..=-10000000000000 => 15,
326 -9999999999999..=-1000000000000 => 14,
327 -999999999999..=-100000000000 => 13,
328 -99999999999..=-10000000000 => 12,
329 -9999999999..=-1000000000 => 11,
330 -999999999..=-100000000 => 10,
331 -99999999..=-10000000 => 9,
332 -9999999..=-1000000 => 8,
333 -999999..=-100000 => 7,
334 -99999..=-10000 => 6,
335 -9999..=-1000 => 5,
336 -999..=-100 => 4,
337 -99..=-10 => 3,
338 -9..=-1 => 2,
339 0..=9 => 1,
340 10..=99 => 2,
341 100..=999 => 3,
342 1000..=9999 => 4,
343 10000..=99999 => 5,
344 100000..=999999 => 6,
345 1000000..=9999999 => 7,
346 10000000..=99999999 => 8,
347 100000000..=999999999 => 9,
348 1000000000..=9999999999 => 10,
349 10000000000..=99999999999 => 11,
350 100000000000..=999999999999 => 12,
351 1000000000000..=9999999999999 => 13,
352 10000000000000..=99999999999999 => 14,
353 100000000000000..=999999999999999 => 15,
354 1000000000000000..=9999999999999999 => 16,
355 10000000000000000..=99999999999999999 => 17,
356 100000000000000000..=999999999999999999 => 18,
357 1000000000000000000..=i64::MAX => 19,
358 }
359 }
360}
361
362#[cfg(target_pointer_width = "64")]
363impl DigitCount for usize {
364 #[inline(always)]
365 fn digit_count(self) -> usize {
366 DigitCount::digit_count(self as u64)
367 }
368}
369
370#[cfg(target_pointer_width = "32")]
371impl DigitCount for usize {
372 #[inline(always)]
373 fn digit_count(self) -> usize {
374 DigitCount::digit_count(self as u32)
375 }
376}
377
378#[cfg(target_pointer_width = "64")]
379impl DigitCount for isize {
380 #[inline(always)]
381 fn digit_count(self) -> usize {
382 DigitCount::digit_count(self as i64)
383 }
384}
385
386#[cfg(target_pointer_width = "32")]
387impl DigitCount for isize {
388 #[inline(always)]
389 fn digit_count(self) -> usize {
390 DigitCount::digit_count(self as i32)
391 }
392}