Coverage Report

Created: 2025-12-12 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ryu-1.0.10/src/buffer/mod.rs
Line
Count
Source
1
use crate::raw;
2
use core::mem::MaybeUninit;
3
use core::{slice, str};
4
#[cfg(feature = "no-panic")]
5
use no_panic::no_panic;
6
7
const NAN: &str = "NaN";
8
const INFINITY: &str = "inf";
9
const NEG_INFINITY: &str = "-inf";
10
11
/// Safe API for formatting floating point numbers to text.
12
///
13
/// ## Example
14
///
15
/// ```
16
/// let mut buffer = ryu::Buffer::new();
17
/// let printed = buffer.format_finite(1.234);
18
/// assert_eq!(printed, "1.234");
19
/// ```
20
pub struct Buffer {
21
    bytes: [MaybeUninit<u8>; 24],
22
}
23
24
impl Buffer {
25
    /// This is a cheap operation; you don't need to worry about reusing buffers
26
    /// for efficiency.
27
    #[inline]
28
    #[cfg_attr(feature = "no-panic", no_panic)]
29
0
    pub fn new() -> Self {
30
0
        let bytes = [MaybeUninit::<u8>::uninit(); 24];
31
0
        Buffer { bytes }
32
0
    }
Unexecuted instantiation: <ryu::buffer::Buffer>::new
Unexecuted instantiation: <ryu::buffer::Buffer>::new
Unexecuted instantiation: <ryu::buffer::Buffer>::new
33
34
    /// Print a floating point number into this buffer and return a reference to
35
    /// its string representation within the buffer.
36
    ///
37
    /// # Special cases
38
    ///
39
    /// This function formats NaN as the string "NaN", positive infinity as
40
    /// "inf", and negative infinity as "-inf" to match std::fmt.
41
    ///
42
    /// If your input is known to be finite, you may get better performance by
43
    /// calling the `format_finite` method instead of `format` to avoid the
44
    /// checks for special cases.
45
    #[cfg_attr(feature = "no-panic", inline)]
46
    #[cfg_attr(feature = "no-panic", no_panic)]
47
0
    pub fn format<F: Float>(&mut self, f: F) -> &str {
48
0
        if f.is_nonfinite() {
49
0
            f.format_nonfinite()
50
        } else {
51
0
            self.format_finite(f)
52
        }
53
0
    }
54
55
    /// Print a floating point number into this buffer and return a reference to
56
    /// its string representation within the buffer.
57
    ///
58
    /// # Special cases
59
    ///
60
    /// This function **does not** check for NaN or infinity. If the input
61
    /// number is not a finite float, the printed representation will be some
62
    /// correctly formatted but unspecified numerical value.
63
    ///
64
    /// Please check [`is_finite`] yourself before calling this function, or
65
    /// check [`is_nan`] and [`is_infinite`] and handle those cases yourself.
66
    ///
67
    /// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_finite
68
    /// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_nan
69
    /// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite
70
    #[inline]
71
    #[cfg_attr(feature = "no-panic", no_panic)]
72
0
    pub fn format_finite<F: Float>(&mut self, f: F) -> &str {
73
        unsafe {
74
0
            let n = f.write_to_ryu_buffer(self.bytes.as_mut_ptr() as *mut u8);
75
0
            debug_assert!(n <= self.bytes.len());
76
0
            let slice = slice::from_raw_parts(self.bytes.as_ptr() as *const u8, n);
77
0
            str::from_utf8_unchecked(slice)
78
        }
79
0
    }
Unexecuted instantiation: <ryu::buffer::Buffer>::format_finite::<f64>
Unexecuted instantiation: <ryu::buffer::Buffer>::format_finite::<_>
80
}
81
82
impl Copy for Buffer {}
83
84
impl Clone for Buffer {
85
    #[inline]
86
0
    fn clone(&self) -> Self {
87
0
        Buffer::new()
88
0
    }
89
}
90
91
impl Default for Buffer {
92
    #[inline]
93
    #[cfg_attr(feature = "no-panic", no_panic)]
94
0
    fn default() -> Self {
95
0
        Buffer::new()
96
0
    }
97
}
98
99
/// A floating point number, f32 or f64, that can be written into a
100
/// [`ryu::Buffer`][Buffer].
101
///
102
/// This trait is sealed and cannot be implemented for types outside of the
103
/// `ryu` crate.
104
pub trait Float: Sealed {}
105
impl Float for f32 {}
106
impl Float for f64 {}
107
108
pub trait Sealed: Copy {
109
    fn is_nonfinite(self) -> bool;
110
    fn format_nonfinite(self) -> &'static str;
111
    unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize;
112
}
113
114
impl Sealed for f32 {
115
    #[inline]
116
0
    fn is_nonfinite(self) -> bool {
117
        const EXP_MASK: u32 = 0x7f800000;
118
0
        let bits = self.to_bits();
119
0
        bits & EXP_MASK == EXP_MASK
120
0
    }
121
122
    #[cold]
123
    #[cfg_attr(feature = "no-panic", inline)]
124
0
    fn format_nonfinite(self) -> &'static str {
125
        const MANTISSA_MASK: u32 = 0x007fffff;
126
        const SIGN_MASK: u32 = 0x80000000;
127
0
        let bits = self.to_bits();
128
0
        if bits & MANTISSA_MASK != 0 {
129
0
            NAN
130
0
        } else if bits & SIGN_MASK != 0 {
131
0
            NEG_INFINITY
132
        } else {
133
0
            INFINITY
134
        }
135
0
    }
136
137
    #[inline]
138
0
    unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
139
0
        raw::format32(self, result)
140
0
    }
141
}
142
143
impl Sealed for f64 {
144
    #[inline]
145
0
    fn is_nonfinite(self) -> bool {
146
        const EXP_MASK: u64 = 0x7ff0000000000000;
147
0
        let bits = self.to_bits();
148
0
        bits & EXP_MASK == EXP_MASK
149
0
    }
150
151
    #[cold]
152
    #[cfg_attr(feature = "no-panic", inline)]
153
0
    fn format_nonfinite(self) -> &'static str {
154
        const MANTISSA_MASK: u64 = 0x000fffffffffffff;
155
        const SIGN_MASK: u64 = 0x8000000000000000;
156
0
        let bits = self.to_bits();
157
0
        if bits & MANTISSA_MASK != 0 {
158
0
            NAN
159
0
        } else if bits & SIGN_MASK != 0 {
160
0
            NEG_INFINITY
161
        } else {
162
0
            INFINITY
163
        }
164
0
    }
165
166
    #[inline]
167
0
    unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
168
0
        raw::format64(self, result)
169
0
    }
Unexecuted instantiation: <f64 as ryu::buffer::Sealed>::write_to_ryu_buffer
Unexecuted instantiation: <f64 as ryu::buffer::Sealed>::write_to_ryu_buffer
170
}