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