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 = "1.98.0")]
18            impl NumBufferTrait for $signed {
19                // `+ 2` and not `+ 1` to include the `-` character.
20                const DEFAULT: Self::Buf = [MaybeUninit::<u8>::uninit(); $signed::MAX.ilog10() as usize + 2];
21                type Buf = [MaybeUninit<u8>; $signed::MAX.ilog10() as usize + 2];
22            }
23            #[stable(feature = "int_format_into", since = "1.98.0")]
24            impl NumBufferTrait for $unsigned {
25                const DEFAULT: Self::Buf = [MaybeUninit::<u8>::uninit(); $unsigned::MAX.ilog10() as usize + 1];
26                type Buf = [MaybeUninit<u8>; $unsigned::MAX.ilog10() 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/// Memory for formatting numbers using [`T::format_into()`][u8::format_into].
42///
43/// This type consists of enough memory to hold the longest decimal string representation
44/// a number of type `T` could have.
45/// It is used only by calling `format_into()`; there is no other way to access its contents.
46/// Its purpose is to allow formatting numbers without involving the dynamic dispatch of the
47/// [`fmt`] system, which may be more efficient when [`fmt`] is not otherwise used.
48///
49/// [`fmt`]: crate::fmt
50///
51/// # Examples
52///
53/// ```
54/// use core::fmt::NumBuffer;
55///
56/// let mut buf = NumBuffer::new();
57/// let n1 = 1972u32;
58/// assert_eq!(n1.format_into(&mut buf), "1972");
59///
60/// // Formatting a negative integer includes the sign.
61/// let mut buf = NumBuffer::new();
62/// let n2 = -1972i32;
63/// assert_eq!(n2.format_into(&mut buf), "-1972");
64/// ```
65#[stable(feature = "int_format_into", since = "1.98.0")]
66pub struct NumBuffer<T: NumBufferTrait> {
67    pub(crate) buf: T::Buf,
68    phantom: core::marker::PhantomData<T>,
69}
70
71#[stable(feature = "int_format_into", since = "1.98.0")]
72impl<T: NumBufferTrait> core::fmt::Debug for NumBuffer<T> {
73    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
74        f.debug_struct("NumBuffer").finish()
75    }
76}
77
78#[stable(feature = "int_format_into", since = "1.98.0")]
79impl<T: NumBufferTrait> NumBuffer<T> {
80    /// Initializes internal buffer.
81    #[stable(feature = "int_format_into", since = "1.98.0")]
82    #[rustc_const_stable(feature = "int_format_into", since = "1.98.0")]
83    pub const fn new() -> Self {
84        NumBuffer { buf: T::DEFAULT, phantom: core::marker::PhantomData }
85    }
86}