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 {}