1 //! Slow, simple lexical integer-to-string conversion routine.
2 
3 use crate::util::*;
4 
5 // Naive itoa algorithm.
6 macro_rules! naive_algorithm {
7     ($value:ident, $radix:ident, $buffer:ident, $index:ident) => ({
8         while $value >= $radix {
9             let r = ($value % $radix).as_usize();
10             $value /= $radix;
11 
12             // This is always safe, since r must be [0, radix).
13             $index -= 1;
14             unchecked_index_mut!($buffer[$index] = digit_to_char(r));
15         }
16 
17         // Decode last digit.
18         let r = ($value % $radix).as_usize();
19         // This is always safe, since r must be [0, radix).
20         $index -= 1;
21         unchecked_index_mut!($buffer[$index] = digit_to_char(r));
22     });
23 }
24 
25 // Naive implementation for radix-N numbers.
26 // Precondition: `value` must be non-negative and mutable.
27 perftools_inline!{
28 fn naive<T>(mut value: T, radix: u32, buffer: &mut [u8])
29     -> usize
30     where T: UnsignedInteger
31 {
32     // Decode all but last digit, 1 at a time.
33     let mut index = buffer.len();
34     let radix: T = as_cast(radix);
35     naive_algorithm!(value, radix, buffer, index);
36     index
37 }}
38 
39 pub(crate) trait Naive {
40     // Export integer to string.
naive(self, radix: u32, buffer: &mut [u8]) -> usize41     fn naive(self, radix: u32, buffer: &mut [u8]) -> usize;
42 }
43 
44 // Implement naive for type.
45 macro_rules! naive_impl {
46     ($($t:ty)*) => ($(
47         impl Naive for $t {
48             perftools_inline_always!{
49             fn naive(self, radix: u32, buffer: &mut [u8]) -> usize {
50                 naive(self, radix, buffer)
51             }}
52         }
53     )*);
54 }
55 
56 naive_impl! { u8 u16 u32 u64 usize }
57 
58 // Naive implementation for 128-bit radix-N numbers.
59 // Precondition: `value` must be non-negative and mutable.
60 perftools_inline!{
61 fn naive_u128(value: u128, radix: u32, buffer: &mut [u8])
62     -> usize
63 {
64     // Decode all but last digit, 1 at a time.
65     let (divisor, digits_per_iter, d_cltz) = u128_divisor(radix);
66     let radix: u64 = as_cast(radix);
67 
68     // To deal with internal 0 values or values with internal 0 digits set,
69     // we store the starting index, and if not all digits are written,
70     // we just skip down `digits` digits for the next value.
71     let mut index = buffer.len();
72     let mut start_index = index;
73     let (value, mut low) = u128_divrem(value, divisor, d_cltz);
74     naive_algorithm!(low, radix, buffer, index);
75     if value != 0 {
76         start_index -= digits_per_iter;
77         index = index.min(start_index);
78         let (value, mut mid) = u128_divrem(value, divisor, d_cltz);
79         naive_algorithm!(mid, radix, buffer, index);
80 
81         if value != 0 {
82             start_index -= digits_per_iter;
83             index = index.min(start_index);
84             let mut high = value as u64;
85             naive_algorithm!(high, radix, buffer, index);
86         }
87     }
88     index
89 }}
90 
91 impl Naive for u128 {
92     perftools_inline_always!{
93     fn naive(self, radix: u32, buffer: &mut [u8]) -> usize {
94         naive_u128(self, radix, buffer)
95     }}
96 }
97