ryu_ecmascript/buffer/mod.rs
1use core::{mem, slice, str};
2
3use pretty;
4
5#[cfg(feature = "no-panic")]
6use no_panic::no_panic;
7
8/// Safe API for formatting floating point numbers to text.
9///
10/// ## Example
11///
12/// ```rust
13/// let mut buffer = ryu_ecmascript::Buffer::new();
14/// let printed = buffer.format(1.234);
15/// assert_eq!(printed, "1.234");
16/// ```
17#[derive(Copy, Clone)]
18pub struct Buffer {
19 bytes: [u8; 25],
20}
21
22impl Buffer {
23 /// This is a cheap operation; you don't need to worry about reusing buffers
24 /// for efficiency.
25 #[inline]
26 #[cfg_attr(feature = "no-panic", no_panic)]
27 pub fn new() -> Self {
28 Buffer { bytes: unsafe { mem::uninitialized() } }
29 }
30
31 /// Print a floating point number into this buffer and return a reference to
32 /// its string representation within the buffer.
33 ///
34 /// # Special cases
35 ///
36 /// This function **does not** check for NaN or infinity. If the input
37 /// number is not a finite float, the printed representation will be some
38 /// correctly formatted but unspecified numerical value.
39 ///
40 /// Please check [`is_finite`] yourself before calling this function, or
41 /// check [`is_nan`] and [`is_infinite`] and handle those cases yourself.
42 ///
43 /// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_finite
44 /// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_nan
45 /// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite
46 #[inline]
47 #[cfg_attr(feature = "no-panic", no_panic)]
48 pub fn format<F: Float>(&mut self, f: F) -> &str {
49 unsafe {
50 let n = f.write_to_ryu_buffer(&mut self.bytes[0]);
51 debug_assert!(n <= self.bytes.len());
52 let slice = slice::from_raw_parts(&self.bytes[0], n);
53 str::from_utf8_unchecked(slice)
54 }
55 }
56}
57
58impl Default for Buffer {
59 #[inline]
60 #[cfg_attr(feature = "no-panic", no_panic)]
61 fn default() -> Self {
62 Buffer::new()
63 }
64}
65
66/// A floating point number, f32 or f64, that can be written into a
67/// [`ryu_ecmascript::Buffer`][Buffer].
68///
69/// This trait is sealed and cannot be implemented for types outside of the
70/// `ryu` crate.
71pub trait Float: Sealed {
72 // Not public API.
73 #[doc(hidden)]
74 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize;
75}
76
77impl Float for f32 {
78 #[inline]
79 #[cfg_attr(feature = "no-panic", no_panic)]
80 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
81 pretty::f2s_buffered_n(self, result)
82 }
83}
84
85impl Float for f64 {
86 #[inline]
87 #[cfg_attr(feature = "no-panic", no_panic)]
88 unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
89 pretty::d2s_buffered_n(self, result)
90 }
91}
92
93pub trait Sealed {}
94impl Sealed for f32 {}
95impl Sealed for f64 {}