ryu/buffer/
mod.rs
1use crate::raw;
2use core::mem::MaybeUninit;
3use core::{slice, str};
4#[cfg(feature = "no-panic")]
5use no_panic::no_panic;
6
7const NAN: &str = "NaN";
8const INFINITY: &str = "inf";
9const NEG_INFINITY: &str = "-inf";
10
11pub struct Buffer {
21 bytes: [MaybeUninit<u8>; 24],
22}
23
24impl Buffer {
25 #[inline]
28 #[cfg_attr(feature = "no-panic", no_panic)]
29 pub fn new() -> Self {
30 let bytes = [MaybeUninit::<u8>::uninit(); 24];
31 Buffer { bytes }
32 }
33
34 #[cfg_attr(feature = "no-panic", inline)]
46 #[cfg_attr(feature = "no-panic", no_panic)]
47 pub fn format<F: Float>(&mut self, f: F) -> &str {
48 if f.is_nonfinite() {
49 f.format_nonfinite()
50 } else {
51 self.format_finite(f)
52 }
53 }
54
55 #[inline]
71 #[cfg_attr(feature = "no-panic", no_panic)]
72 pub fn format_finite<F: Float>(&mut self, f: F) -> &str {
73 unsafe {
74 let n = f.write_to_ryu_buffer(self.bytes.as_mut_ptr() as *mut u8);
75 debug_assert!(n <= self.bytes.len());
76 let slice = slice::from_raw_parts(self.bytes.as_ptr() as *const u8, n);
77 str::from_utf8_unchecked(slice)
78 }
79 }
80}
81
82impl Copy for Buffer {}
83
84impl Clone for Buffer {
85 #[inline]
86 #[allow(clippy::non_canonical_clone_impl)] fn clone(&self) -> Self {
88 Buffer::new()
89 }
90}
91
92impl Default for Buffer {
93 #[inline]
94 #[cfg_attr(feature = "no-panic", no_panic)]
95 fn default() -> Self {
96 Buffer::new()
97 }
98}
99
100pub trait Float: Sealed {}
106impl Float for f32 {}
107impl Float for f64 {}
108
109pub trait Sealed: Copy {
110 fn is_nonfinite(self) -> bool;
111 fn format_nonfinite(self) -> &'static str;
112 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize;
113}
114
115impl Sealed for f32 {
116 #[inline]
117 fn is_nonfinite(self) -> bool {
118 const EXP_MASK: u32 = 0x7f800000;
119 let bits = self.to_bits();
120 bits & EXP_MASK == EXP_MASK
121 }
122
123 #[cold]
124 #[cfg_attr(feature = "no-panic", inline)]
125 fn format_nonfinite(self) -> &'static str {
126 const MANTISSA_MASK: u32 = 0x007fffff;
127 const SIGN_MASK: u32 = 0x80000000;
128 let bits = self.to_bits();
129 if bits & MANTISSA_MASK != 0 {
130 NAN
131 } else if bits & SIGN_MASK != 0 {
132 NEG_INFINITY
133 } else {
134 INFINITY
135 }
136 }
137
138 #[inline]
139 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
140 raw::format32(self, result)
141 }
142}
143
144impl Sealed for f64 {
145 #[inline]
146 fn is_nonfinite(self) -> bool {
147 const EXP_MASK: u64 = 0x7ff0000000000000;
148 let bits = self.to_bits();
149 bits & EXP_MASK == EXP_MASK
150 }
151
152 #[cold]
153 #[cfg_attr(feature = "no-panic", inline)]
154 fn format_nonfinite(self) -> &'static str {
155 const MANTISSA_MASK: u64 = 0x000fffffffffffff;
156 const SIGN_MASK: u64 = 0x8000000000000000;
157 let bits = self.to_bits();
158 if bits & MANTISSA_MASK != 0 {
159 NAN
160 } else if bits & SIGN_MASK != 0 {
161 NEG_INFINITY
162 } else {
163 INFINITY
164 }
165 }
166
167 #[inline]
168 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
169 raw::format64(self, result)
170 }
171}