Skip to main content

core/fmt/
num_buffer.rs

1use crate::mem::MaybeUninit;
2
3/// Trait used to describe the maximum number of digits in decimal base of the implemented integer.
4#[unstable(feature = "fmt_internals", issue = "none")]
5pub trait NumBufferTrait {
6    /// Maximum number of digits in decimal base of the implemented integer.
7    #[unstable(feature = "fmt_internals", issue = "none")]
8    const BUF_SIZE: usize;
9}
10
11macro_rules! impl_NumBufferTrait {
12    ($($signed:ident, $unsigned:ident,)*) => {
13        $(
14            #[stable(feature = "int_format_into", since = "CURRENT_RUSTC_VERSION")]
15            impl NumBufferTrait for $signed {
16                // `+ 2` and not `+ 1` to include the `-` character.
17                const BUF_SIZE: usize = $signed::MAX.ilog(10) as usize + 2;
18            }
19            #[stable(feature = "int_format_into", since = "CURRENT_RUSTC_VERSION")]
20            impl NumBufferTrait for $unsigned {
21                const BUF_SIZE: usize = $unsigned::MAX.ilog(10) as usize + 1;
22            }
23        )*
24    }
25}
26
27impl_NumBufferTrait! {
28    i8, u8,
29    i16, u16,
30    i32, u32,
31    i64, u64,
32    isize, usize,
33    i128, u128,
34}
35
36/// A buffer wrapper of which the internal size is based on the maximum
37/// number of digits the associated integer can have.
38///
39/// # Examples
40///
41/// ```
42/// use core::fmt::NumBuffer;
43///
44/// let mut buf = NumBuffer::new();
45/// let n1 = 1972u32;
46/// assert_eq!(n1.format_into(&mut buf), "1972");
47///
48/// // Formatting a negative integer includes the sign.
49/// let mut buf = NumBuffer::new();
50/// let n2 = -1972i32;
51/// assert_eq!(n2.format_into(&mut buf), "-1972");
52/// ```
53#[stable(feature = "int_format_into", since = "CURRENT_RUSTC_VERSION")]
54pub struct NumBuffer<T: NumBufferTrait> {
55    // FIXME: Once const generics feature is working, use `T::BUF_SIZE` instead of 40.
56    pub(crate) buf: [MaybeUninit<u8>; 40],
57    // FIXME: Remove this field once we can actually use `T`.
58    phantom: core::marker::PhantomData<T>,
59}
60
61#[stable(feature = "int_format_into", since = "CURRENT_RUSTC_VERSION")]
62impl<T: NumBufferTrait> core::fmt::Debug for NumBuffer<T> {
63    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64        f.debug_struct("NumBuffer").finish()
65    }
66}
67
68#[stable(feature = "int_format_into", since = "CURRENT_RUSTC_VERSION")]
69impl<T: NumBufferTrait> NumBuffer<T> {
70    /// Initializes internal buffer.
71    #[stable(feature = "int_format_into", since = "CURRENT_RUSTC_VERSION")]
72    #[rustc_const_stable(feature = "int_format_into", since = "CURRENT_RUSTC_VERSION")]
73    pub const fn new() -> Self {
74        // FIXME: Once const generics feature is working, use `T::BUF_SIZE` instead of 40.
75        NumBuffer { buf: [MaybeUninit::<u8>::uninit(); 40], phantom: core::marker::PhantomData }
76    }
77
78    pub(crate) const fn capacity(&self) -> usize {
79        self.buf.len()
80    }
81}