-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Make int_format_into
API more flexible
#143636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
//! Integer and floating-point number formatting | ||
|
||
use crate::fmt::NumBuffer; | ||
use crate::fmt::{NumBuffer, NumBufferTrait}; | ||
use crate::mem::MaybeUninit; | ||
use crate::num::fmt as numfmt; | ||
use crate::ops::{Div, Rem, Sub}; | ||
|
@@ -338,7 +338,7 @@ macro_rules! impl_Display { | |
/// use core::fmt::NumBuffer; | ||
/// | ||
#[doc = concat!("let n = 0", stringify!($signed), ";")] | ||
/// let mut buf = NumBuffer::new(); | ||
#[doc = concat!("let mut buf = NumBuffer::<", stringify!($signed), ">::new();")] | ||
/// assert_eq!(n.format_into(&mut buf), "0"); | ||
/// | ||
#[doc = concat!("let n1 = 32", stringify!($signed), ";")] | ||
|
@@ -347,8 +347,23 @@ macro_rules! impl_Display { | |
#[doc = concat!("let n2 = ", stringify!($signed::MAX), ";")] | ||
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($signed::MAX), ".to_string());")] | ||
/// ``` | ||
/// | ||
/// You can also use a [`NumBuffer`] used to store a bigger integer: | ||
/// | ||
/// ``` | ||
/// #![feature(int_format_into)] | ||
/// use core::fmt::NumBuffer; | ||
/// | ||
#[doc = concat!("let n = 32", stringify!($signed), ";")] | ||
/// // We use a `NumBuffer` used to store a bigger integer. | ||
/// let mut buf = NumBuffer::<u128>::new(); | ||
This comment was marked as resolved.
Sorry, something went wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Also, if it didn't, the doctest would fail because compilation would fail. |
||
/// assert_eq!(n.format_into(&mut buf), "32"); | ||
/// ``` | ||
#[unstable(feature = "int_format_into", issue = "138215")] | ||
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { | ||
pub fn format_into<T: NumBufferTrait>(self, buf: &mut NumBuffer<T>) -> &str { | ||
const { | ||
assert!(Self::BUF_SIZE <= T::BUF_SIZE, "buffer is not big enough"); | ||
} | ||
let mut offset; | ||
|
||
#[cfg(not(feature = "optimize_for_size"))] | ||
|
@@ -381,7 +396,7 @@ macro_rules! impl_Display { | |
/// use core::fmt::NumBuffer; | ||
/// | ||
#[doc = concat!("let n = 0", stringify!($unsigned), ";")] | ||
/// let mut buf = NumBuffer::new(); | ||
#[doc = concat!("let mut buf = NumBuffer::<", stringify!($unsigned), ">::new();")] | ||
/// assert_eq!(n.format_into(&mut buf), "0"); | ||
/// | ||
#[doc = concat!("let n1 = 32", stringify!($unsigned), ";")] | ||
|
@@ -390,8 +405,23 @@ macro_rules! impl_Display { | |
#[doc = concat!("let n2 = ", stringify!($unsigned::MAX), ";")] | ||
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($unsigned::MAX), ".to_string());")] | ||
/// ``` | ||
/// | ||
/// You can also use a [`NumBuffer`] used to store a bigger integer: | ||
/// | ||
/// ``` | ||
/// #![feature(int_format_into)] | ||
/// use core::fmt::NumBuffer; | ||
/// | ||
#[doc = concat!("let n = 32", stringify!($unsigned), ";")] | ||
/// // We use a `NumBuffer` used to store `u128`. | ||
/// let mut buf = NumBuffer::<u128>::new(); | ||
/// assert_eq!(n.format_into(&mut buf), "32"); | ||
/// ``` | ||
#[unstable(feature = "int_format_into", issue = "138215")] | ||
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { | ||
pub fn format_into<T: NumBufferTrait>(self, buf: &mut NumBuffer<T>) -> &str { | ||
const { | ||
assert!(Self::BUF_SIZE <= T::BUF_SIZE, "buffer is not big enough"); | ||
} | ||
let offset; | ||
|
||
#[cfg(not(feature = "optimize_for_size"))] | ||
|
@@ -790,19 +820,20 @@ impl u128 { | |
/// use core::fmt::NumBuffer; | ||
/// | ||
/// let n = 0u128; | ||
/// let mut buf = NumBuffer::new(); | ||
/// let mut buf = NumBuffer::<u128>::new(); | ||
/// assert_eq!(n.format_into(&mut buf), "0"); | ||
/// | ||
/// let n1 = 32u128; | ||
/// let mut buf1 = NumBuffer::new(); | ||
/// assert_eq!(n1.format_into(&mut buf1), "32"); | ||
/// assert_eq!(n1.format_into(&mut buf), "32"); | ||
/// | ||
/// let n2 = u128::MAX; | ||
/// let mut buf2 = NumBuffer::new(); | ||
/// assert_eq!(n2.format_into(&mut buf2), u128::MAX.to_string()); | ||
/// assert_eq!(n2.format_into(&mut buf), u128::MAX.to_string()); | ||
/// ``` | ||
#[unstable(feature = "int_format_into", issue = "138215")] | ||
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { | ||
pub fn format_into<T: NumBufferTrait>(self, buf: &mut NumBuffer<T>) -> &str { | ||
const { | ||
assert!(Self::BUF_SIZE <= T::BUF_SIZE, "buffer is not big enough"); | ||
} | ||
let diff = buf.capacity() - U128_MAX_DEC_N; | ||
// FIXME: Once const generics are better, use `NumberBufferTrait::BUF_SIZE` as generic const | ||
// for `fmt_u128_inner`. | ||
|
@@ -825,7 +856,7 @@ impl i128 { | |
/// use core::fmt::NumBuffer; | ||
/// | ||
/// let n = 0i128; | ||
/// let mut buf = NumBuffer::new(); | ||
/// let mut buf = NumBuffer::<i128>::new(); | ||
/// assert_eq!(n.format_into(&mut buf), "0"); | ||
/// | ||
/// let n1 = i128::MIN; | ||
|
@@ -835,7 +866,10 @@ impl i128 { | |
/// assert_eq!(n2.format_into(&mut buf), i128::MAX.to_string()); | ||
/// ``` | ||
#[unstable(feature = "int_format_into", issue = "138215")] | ||
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { | ||
pub fn format_into<T: NumBufferTrait>(self, buf: &mut NumBuffer<T>) -> &str { | ||
const { | ||
assert!(Self::BUF_SIZE <= T::BUF_SIZE, "buffer is not big enough"); | ||
} | ||
let diff = buf.capacity() - U128_MAX_DEC_N; | ||
// FIXME: Once const generics are better, use `NumberBufferTrait::BUF_SIZE` as generic const | ||
// for `fmt_u128_inner`. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Test to ensure that if you use a `NumBuffer` with a too small integer, it | ||
// will fail at compilation time. | ||
|
||
//@ build-fail | ||
//@ ignore-pass | ||
|
||
#![feature(int_format_into)] | ||
|
||
use std::fmt::NumBuffer; | ||
|
||
fn main() { | ||
let x = 0u32; | ||
let mut buf = NumBuffer::<u8>::new(); | ||
x.format_into(&mut buf); | ||
} | ||
|
||
//~? ERROR evaluation panicked |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
error[E0080]: evaluation panicked: buffer is not big enough | ||
--> $SRC_DIR/core/src/fmt/num.rs:LL:COL | ||
::: $SRC_DIR/core/src/fmt/num.rs:LL:COL | ||
| | ||
= note: evaluation of `core::fmt::num::imp::<impl u32>::format_into::<u8>::{constant#0}` failed here | ||
| | ||
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `impl_Display` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
note: erroneous constant encountered | ||
--> $SRC_DIR/core/src/fmt/num.rs:LL:COL | ||
| | ||
= note: this note originates in the macro `impl_Display` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
note: the above error was encountered while instantiating `fn core::fmt::num::imp::<impl u32>::format_into::<u8>` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That this is a post-mono error is another small downside of this PR. There's a policy that |
||
--> $DIR/fmt.rs:14:5 | ||
| | ||
LL | x.format_into(&mut buf); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to 1 previous error | ||
|
||
For more information about this error, try `rustc --explain E0080`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needing to specify/repeat the type when creating the buffer seems like a non-trivial downside. I'm not sure if the added flexibility is worth it. Can you give a semi-realistic example of where you'd want the flexibility of formatting one of several integer types into the same buffer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to have only one buffer across your program life to fit all your integers that have different sizes, it's quite convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When would I want such a long-lived buffer? Every usage of
itoa
I've seen while researching for the ACP just creates a new temporary buffer on the spot whenever it needs to format an integer. I don't think I've even seen a single buffer used twice for the same integer type. Setting up a buffer doesn't have any cost that needs to be amortized, allocating some extra uninitialized space in your stack frame is as close to free as it gets. If anything, putting the buffer somewhere else has a higher risk that it's moved around, which generally implies copying the whole buffer!