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