ryu/buffer/
mod.rs
1use core::{mem, slice, str};
2
3#[cfg(maybe_uninit)]
4use core::mem::MaybeUninit;
5
6use raw;
7
8#[cfg(feature = "no-panic")]
9use no_panic::no_panic;
10
11const NAN: &'static str = "NaN";
12const INFINITY: &'static str = "inf";
13const NEG_INFINITY: &'static str = "-inf";
14
15#[derive(Copy, Clone)]
25pub struct Buffer {
26 #[cfg(maybe_uninit)]
27 bytes: [MaybeUninit<u8>; 24],
28 #[cfg(not(maybe_uninit))]
29 bytes: [u8; 24],
30}
31
32impl Buffer {
33 #[inline]
36 #[cfg_attr(feature = "no-panic", no_panic)]
37 pub fn new() -> Self {
38 #[cfg(maybe_uninit)]
41 let bytes = [MaybeUninit::<u8>::uninit(); 24];
42 #[cfg(not(maybe_uninit))]
43 let bytes = unsafe { mem::uninitialized() };
44
45 Buffer { bytes: bytes }
46 }
47
48 #[cfg_attr(feature = "no-panic", inline)]
60 #[cfg_attr(feature = "no-panic", no_panic)]
61 pub fn format<F: Float>(&mut self, f: F) -> &str {
62 if f.is_nonfinite() {
63 f.format_nonfinite()
64 } else {
65 self.format_finite(f)
66 }
67 }
68
69 #[inline]
85 #[cfg_attr(feature = "no-panic", no_panic)]
86 pub fn format_finite<F: Float>(&mut self, f: F) -> &str {
87 unsafe {
88 let n = f.write_to_ryu_buffer(self.first_byte_pointer_mut());
89 debug_assert!(n <= self.bytes.len());
90 let slice = slice::from_raw_parts(self.first_byte_pointer(), n);
91 str::from_utf8_unchecked(slice)
92 }
93 }
94
95 #[inline]
96 #[cfg(maybe_uninit)]
97 fn first_byte_pointer(&self) -> *const u8 {
98 self.bytes[0].as_ptr()
99 }
100
101 #[inline]
102 #[cfg(not(maybe_uninit))]
103 fn first_byte_pointer(&self) -> *const u8 {
104 &self.bytes[0] as *const u8
105 }
106
107 #[inline]
108 #[cfg(maybe_uninit)]
109 fn first_byte_pointer_mut(&mut self) -> *mut u8 {
110 self.bytes[0].as_mut_ptr()
111 }
112
113 #[inline]
114 #[cfg(not(maybe_uninit))]
115 fn first_byte_pointer_mut(&mut self) -> *mut u8 {
116 &mut self.bytes[0] as *mut u8
117 }
118}
119
120impl Default for Buffer {
121 #[inline]
122 #[cfg_attr(feature = "no-panic", no_panic)]
123 fn default() -> Self {
124 Buffer::new()
125 }
126}
127
128pub trait Float: Sealed {}
134impl Float for f32 {}
135impl Float for f64 {}
136
137pub trait Sealed: Copy {
138 fn is_nonfinite(self) -> bool;
139 fn format_nonfinite(self) -> &'static str;
140 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize;
141}
142
143impl Sealed for f32 {
144 #[inline]
145 fn is_nonfinite(self) -> bool {
146 const EXP_MASK: u32 = 0x7f800000;
147 let bits = unsafe { mem::transmute::<f32, u32>(self) };
148 bits & EXP_MASK == EXP_MASK
149 }
150
151 #[cold]
152 #[cfg_attr(feature = "no-panic", inline)]
153 fn format_nonfinite(self) -> &'static str {
154 const MANTISSA_MASK: u32 = 0x007fffff;
155 const SIGN_MASK: u32 = 0x80000000;
156 let bits = unsafe { mem::transmute::<f32, u32>(self) };
157 if bits & MANTISSA_MASK != 0 {
158 NAN
159 } else if bits & SIGN_MASK != 0 {
160 NEG_INFINITY
161 } else {
162 INFINITY
163 }
164 }
165
166 #[inline]
167 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
168 raw::format32(self, result)
169 }
170}
171
172impl Sealed for f64 {
173 #[inline]
174 fn is_nonfinite(self) -> bool {
175 const EXP_MASK: u64 = 0x7ff0000000000000;
176 let bits = unsafe { mem::transmute::<f64, u64>(self) };
177 bits & EXP_MASK == EXP_MASK
178 }
179
180 #[cold]
181 #[cfg_attr(feature = "no-panic", inline)]
182 fn format_nonfinite(self) -> &'static str {
183 const MANTISSA_MASK: u64 = 0x000fffffffffffff;
184 const SIGN_MASK: u64 = 0x8000000000000000;
185 let bits = unsafe { mem::transmute::<f64, u64>(self) };
186 if bits & MANTISSA_MASK != 0 {
187 NAN
188 } else if bits & SIGN_MASK != 0 {
189 NEG_INFINITY
190 } else {
191 INFINITY
192 }
193 }
194
195 #[inline]
196 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
197 raw::format64(self, result)
198 }
199}