Files
aho_corasick
ansi_term
array_tool
atty
bitflags
cargo_update
cfg_if
clap
dirs
dirs_sys
form_urlencoded
git2
hex
idna
json
lazy_static
lazysort
libc
libgit2_sys
libssh2_sys
libz_sys
log
matches
maybe_uninit
memchr
openssl_probe
openssl_sys
percent_encoding
proc_macro2
quote
regex
regex_syntax
semver
semver_parser
serde
serde_derive
smallvec
strsim
syn
tabwriter
term_size
textwrap
toml
unicode_bidi
unicode_normalization
unicode_width
unicode_xid
url
vec_map
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// This is a modified version of the `itoa` crate by David Tolnay:
// https://github.com/dtolnay/itoa
//
// The crate itself borrows code from the stdlib of Rust.
//
// The algorithm here was modified from being able to just writing integers,
// to printing decimal floating points.

use std::{io, mem, ptr, slice};

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const ZEROFILL: &'static [u8] = &[b'0'; 20];

#[inline(always)]
unsafe fn write_num(n: &mut u64, curr: &mut isize, buf_ptr: *mut u8, lut_ptr: *const u8) {
    // eagerly decode 4 digits at a time
    while *n >= 10000 {
        let rem = (*n % 10000) as isize;
        *n /= 10000;

        let d1 = (rem / 100) << 1;
        let d2 = (rem % 100) << 1;
        *curr -= 4;
        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(*curr), 2);
        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(*curr + 2), 2);
    }

    // decode 2 more digits
    if *n >= 100 {
        let d1 = ((*n % 100) << 1) as isize;
        *n /= 100;
        *curr -= 2;
        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(*curr), 2);
    }

    // decode last 1 or 2 digits
    if *n < 10 {
        *curr -= 1;
        *buf_ptr.offset(*curr) = (*n as u8) + b'0';
    } else {
        let d1 = (*n << 1) as isize;
        *curr -= 2;
        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(*curr), 2);
    }
}

pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, exponent: i16) -> io::Result<()> {
    if !positive {
        try!(wr.write_all(b"-"));
    }

    if n == 0 {
        return wr.write_all(b"0");
    }

    let mut buf: [u8; 30] = mem::uninitialized();
    let mut curr = buf.len() as isize;
    let buf_ptr = buf.as_mut_ptr();
    let lut_ptr = DEC_DIGITS_LUT.as_ptr();

    if exponent == 0 {
        write_num(&mut n, &mut curr, buf_ptr, lut_ptr);

        return wr.write_all(
            slice::from_raw_parts(
                buf_ptr.offset(curr),
                buf.len() - curr as usize
            )
        );
    } else if exponent < 0 {
        let mut e = safe_abs(exponent);

        // Decimal number with a fraction that's fully printable
        if e < 18 {
            // eagerly decode 4 digits at a time
            for _ in 0 .. e >> 2 {
                let rem = (n % 10000) as isize;
                n /= 10000;

                let d1 = (rem / 100) << 1;
                let d2 = (rem % 100) << 1;
                curr -= 4;
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
            }

            e &= 3;

            // write the remaining 3, 2 or 1 digits
            if e & 2 == 2 {
                let d1 = ((n % 100) << 1) as isize;
                n /= 100;
                curr -= 2;
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
            }

            if e & 1 == 1 {
                curr -= 1;
                *buf_ptr.offset(curr) = ((n % 10) as u8) + b'0';
                n /= 10;
            }

            curr -= 1;
            *buf_ptr.offset(curr) = b'.';

            write_num(&mut n, &mut curr, buf_ptr, lut_ptr);

            return wr.write_all(
                slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)
            );
        }

        // Not easily printable, write down fraction, then full number, then exponent

        // Since we move the decimal point right after the first digit, we have to adjust the
        // exponent part. If the number is long enough, this may result in the exponent switching
        // sign from negative to positive - we have to handle this case separately.
        let mut exponent_positive = false;
        if n < 10 {
            // Single digit, no fraction
            curr -= 1;
            *buf_ptr.offset(curr) = ((n % 10) as u8) + b'0';
        } else {
            // eagerly decode 4 digits at a time
            while n >= 100000 {
                let rem = (n % 10000) as isize;
                n /= 10000;

                let d1 = (rem / 100) << 1;
                let d2 = (rem % 100) << 1;
                curr -= 4;
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
            }

            // decode 2 more digits
            if n >= 1000 {
                let d1 = ((n % 100) << 1) as isize;
                n /= 100;
                curr -= 2;
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
            }

            // decode last 1 or 2 digits
            if n < 100 {
                curr -= 1;
                *buf_ptr.offset(curr) = ((n % 10) as u8) + b'0';
                n /= 10;
            } else {
                let d1 = ((n % 100) << 1) as isize;
                n /= 100;
                curr -= 2;
                ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
            }

            let printed_so_far = buf.len() as u16 - curr as u16;


            if printed_so_far <= e {
                // Subtract the amount of digits printed in the fraction
                // from the exponent that we still need to print using
                // the `e` notation
                e -= printed_so_far;
            } else {
                // Same as e = |e - printed_so_far|.
                e = printed_so_far - e;
                exponent_positive = true;
            }

            curr -= 1;
            *buf_ptr.offset(curr) = b'.';

            write_num(&mut n, &mut curr, buf_ptr, lut_ptr);
        }

        // Write out the number with a fraction
        try!(wr.write_all(
            slice::from_raw_parts(
                buf_ptr.offset(curr),
                buf.len() - curr as usize
            )
        ));

        // Omit the 'e' notation for e == 0
        if e == 0 {
            return Ok(());
        }
        // Write the remaining `e` notation, with proper sign
        if exponent_positive {
            wr.write_all(b"e+")?;
        } else {
            wr.write_all(b"e-")?;
        }
        return write(wr, true, e as u64, 0);

    }

    // Exponent greater than 0
    write_num(&mut n, &mut curr, buf_ptr, lut_ptr);
    let printed = buf.len() - curr as usize;

    // No need for `e` notation, just print out zeroes
    if (printed + exponent as usize) <= 20 {
        try!(wr.write_all(
            slice::from_raw_parts(
                buf_ptr.offset(curr),
                buf.len() - curr as usize
            )
        ));

        return wr.write_all(&ZEROFILL[ .. exponent as usize]);
    }

    let mut e = exponent as u64;

    // More than one digit, turn into a fraction
    if printed != 1 {
        *buf_ptr.offset(curr - 1) = *buf_ptr.offset(curr);
        *buf_ptr.offset(curr) = b'.';
        curr -= 1;
        e += (printed as u64) - 1;
    }

    try!(wr.write_all(
        slice::from_raw_parts(
            buf_ptr.offset(curr),
            buf.len() - curr as usize
        )
    ));
    try!(wr.write_all(b"e"));
    write(wr, true, e, 0)
}

fn safe_abs(x : i16) -> u16 {
    if let Some(y) = x.checked_abs() {
        y as u16
    } else {
        i16::max_value() as u16 + 1u16
    }
}