Limit formatting width and precision to 16 bits.
This commit is contained in:
parent
2c6a12ec44
commit
fb9ce02976
10 changed files with 69 additions and 46 deletions
|
|
@ -266,7 +266,7 @@ pub enum FormatAlignment {
|
|||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||
pub enum FormatCount {
|
||||
/// `{:5}` or `{:.5}`
|
||||
Literal(usize),
|
||||
Literal(u16),
|
||||
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
|
||||
Argument(FormatArgPosition),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2152,6 +2152,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
pub(super) fn expr_u16(&mut self, sp: Span, value: u16) -> hir::Expr<'hir> {
|
||||
let lit = self.arena.alloc(hir::Lit {
|
||||
span: sp,
|
||||
node: ast::LitKind::Int(
|
||||
u128::from(value).into(),
|
||||
ast::LitIntType::Unsigned(ast::UintTy::U16),
|
||||
),
|
||||
});
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
|
||||
let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) });
|
||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ fn make_count<'hir>(
|
|||
hir::LangItem::FormatCount,
|
||||
sym::Is,
|
||||
));
|
||||
let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, *n)]);
|
||||
let value = ctx.arena.alloc_from_iter([ctx.expr_u16(sp, *n)]);
|
||||
ctx.expr_call_mut(sp, count_is, value)
|
||||
}
|
||||
Some(FormatCount::Argument(arg)) => {
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ pub enum DebugHex {
|
|||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum Count<'a> {
|
||||
/// The count is specified explicitly.
|
||||
CountIs(usize),
|
||||
CountIs(u16),
|
||||
/// The count is specified by the argument with the given name.
|
||||
CountIsName(&'a str, InnerSpan),
|
||||
/// The count is specified by the argument at the given index.
|
||||
|
|
@ -564,7 +564,7 @@ impl<'a> Parser<'a> {
|
|||
/// consuming a macro argument, `None` if it's the case.
|
||||
fn position(&mut self) -> Option<Position<'a>> {
|
||||
if let Some(i) = self.integer() {
|
||||
Some(ArgumentIs(i))
|
||||
Some(ArgumentIs(i.into()))
|
||||
} else {
|
||||
match self.cur.peek() {
|
||||
Some(&(lo, c)) if rustc_lexer::is_id_start(c) => {
|
||||
|
|
@ -770,7 +770,7 @@ impl<'a> Parser<'a> {
|
|||
/// width.
|
||||
fn count(&mut self, start: usize) -> Count<'a> {
|
||||
if let Some(i) = self.integer() {
|
||||
if self.consume('$') { CountIsParam(i) } else { CountIs(i) }
|
||||
if self.consume('$') { CountIsParam(i.into()) } else { CountIs(i) }
|
||||
} else {
|
||||
let tmp = self.cur.clone();
|
||||
let word = self.word();
|
||||
|
|
@ -821,15 +821,15 @@ impl<'a> Parser<'a> {
|
|||
word
|
||||
}
|
||||
|
||||
fn integer(&mut self) -> Option<usize> {
|
||||
let mut cur: usize = 0;
|
||||
fn integer(&mut self) -> Option<u16> {
|
||||
let mut cur: u16 = 0;
|
||||
let mut found = false;
|
||||
let mut overflow = false;
|
||||
let start = self.current_pos();
|
||||
while let Some(&(_, c)) = self.cur.peek() {
|
||||
if let Some(i) = c.to_digit(10) {
|
||||
let (tmp, mul_overflow) = cur.overflowing_mul(10);
|
||||
let (tmp, add_overflow) = tmp.overflowing_add(i as usize);
|
||||
let (tmp, add_overflow) = tmp.overflowing_add(i as u16);
|
||||
if mul_overflow || add_overflow {
|
||||
overflow = true;
|
||||
}
|
||||
|
|
@ -846,11 +846,11 @@ impl<'a> Parser<'a> {
|
|||
let overflowed_int = &self.input[start..end];
|
||||
self.err(
|
||||
format!(
|
||||
"integer `{}` does not fit into the type `usize` whose range is `0..={}`",
|
||||
"integer `{}` does not fit into the type `u16` whose range is `0..={}`",
|
||||
overflowed_int,
|
||||
usize::MAX
|
||||
u16::MAX
|
||||
),
|
||||
"integer out of range for `usize`",
|
||||
"integer out of range for `u16`",
|
||||
self.span(start, end),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1016,6 +1016,7 @@ symbols! {
|
|||
from_residual,
|
||||
from_size_align_unchecked,
|
||||
from_str_method,
|
||||
from_u16,
|
||||
from_usize,
|
||||
from_yeet,
|
||||
fs_create_dir,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ fn float_to_decimal_common_exact<T>(
|
|||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
sign: flt2dec::Sign,
|
||||
precision: usize,
|
||||
precision: u16,
|
||||
) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
|
|
@ -40,7 +40,7 @@ where
|
|||
flt2dec::strategy::grisu::format_exact,
|
||||
*num,
|
||||
sign,
|
||||
precision,
|
||||
precision.into(),
|
||||
&mut buf,
|
||||
&mut parts,
|
||||
);
|
||||
|
|
@ -55,7 +55,7 @@ fn float_to_decimal_common_shortest<T>(
|
|||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
sign: flt2dec::Sign,
|
||||
precision: usize,
|
||||
precision: u16,
|
||||
) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
|
|
@ -68,7 +68,7 @@ where
|
|||
flt2dec::strategy::grisu::format_shortest,
|
||||
*num,
|
||||
sign,
|
||||
precision,
|
||||
precision.into(),
|
||||
&mut buf,
|
||||
&mut parts,
|
||||
);
|
||||
|
|
@ -101,7 +101,7 @@ fn float_to_exponential_common_exact<T>(
|
|||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
sign: flt2dec::Sign,
|
||||
precision: usize,
|
||||
precision: u16,
|
||||
upper: bool,
|
||||
) -> Result
|
||||
where
|
||||
|
|
@ -113,7 +113,7 @@ where
|
|||
flt2dec::strategy::grisu::format_exact,
|
||||
*num,
|
||||
sign,
|
||||
precision,
|
||||
precision.into(),
|
||||
upper,
|
||||
&mut buf,
|
||||
&mut parts,
|
||||
|
|
|
|||
|
|
@ -294,8 +294,8 @@ pub struct FormattingOptions {
|
|||
flags: u32,
|
||||
fill: char,
|
||||
align: Option<Alignment>,
|
||||
width: Option<usize>,
|
||||
precision: Option<usize>,
|
||||
width: Option<u16>,
|
||||
precision: Option<u16>,
|
||||
}
|
||||
|
||||
impl FormattingOptions {
|
||||
|
|
@ -389,7 +389,7 @@ impl FormattingOptions {
|
|||
/// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
|
||||
/// will be used to take up the required space.
|
||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||
pub fn width(&mut self, width: Option<usize>) -> &mut Self {
|
||||
pub fn width(&mut self, width: Option<u16>) -> &mut Self {
|
||||
self.width = width;
|
||||
self
|
||||
}
|
||||
|
|
@ -403,7 +403,7 @@ impl FormattingOptions {
|
|||
/// - For floating-point types, this indicates how many digits after the
|
||||
/// decimal point should be printed.
|
||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||
pub fn precision(&mut self, precision: Option<usize>) -> &mut Self {
|
||||
pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
|
||||
self.precision = precision;
|
||||
self
|
||||
}
|
||||
|
|
@ -455,12 +455,12 @@ impl FormattingOptions {
|
|||
}
|
||||
/// Returns the current width.
|
||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||
pub const fn get_width(&self) -> Option<usize> {
|
||||
pub const fn get_width(&self) -> Option<u16> {
|
||||
self.width
|
||||
}
|
||||
/// Returns the current precision.
|
||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||
pub const fn get_precision(&self) -> Option<usize> {
|
||||
pub const fn get_precision(&self) -> Option<u16> {
|
||||
self.precision
|
||||
}
|
||||
/// Returns the current precision.
|
||||
|
|
@ -1499,15 +1499,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume
|
|||
unsafe { value.fmt(fmt) }
|
||||
}
|
||||
|
||||
unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> {
|
||||
unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
|
||||
match *cnt {
|
||||
#[cfg(bootstrap)]
|
||||
rt::Count::Is(n) => Some(n as u16),
|
||||
#[cfg(not(bootstrap))]
|
||||
rt::Count::Is(n) => Some(n),
|
||||
rt::Count::Implied => None,
|
||||
rt::Count::Param(i) => {
|
||||
debug_assert!(i < args.len());
|
||||
// SAFETY: cnt and args come from the same Arguments,
|
||||
// which guarantees this index is always within bounds.
|
||||
unsafe { args.get_unchecked(i).as_usize() }
|
||||
unsafe { args.get_unchecked(i).as_u16() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1516,11 +1519,11 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize>
|
|||
#[must_use = "don't forget to write the post padding"]
|
||||
pub(crate) struct PostPadding {
|
||||
fill: char,
|
||||
padding: usize,
|
||||
padding: u16,
|
||||
}
|
||||
|
||||
impl PostPadding {
|
||||
fn new(fill: char, padding: usize) -> PostPadding {
|
||||
fn new(fill: char, padding: u16) -> PostPadding {
|
||||
PostPadding { fill, padding }
|
||||
}
|
||||
|
||||
|
|
@ -1634,7 +1637,7 @@ impl<'a> Formatter<'a> {
|
|||
}
|
||||
// Check if we're over the minimum width, if so then we can also
|
||||
// just write the bytes.
|
||||
Some(min) if width >= min => {
|
||||
Some(min) if width >= usize::from(min) => {
|
||||
write_prefix(self, sign, prefix)?;
|
||||
self.buf.write_str(buf)
|
||||
}
|
||||
|
|
@ -1645,7 +1648,7 @@ impl<'a> Formatter<'a> {
|
|||
let old_align =
|
||||
crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
|
||||
write_prefix(self, sign, prefix)?;
|
||||
let post_padding = self.padding(min - width, Alignment::Right)?;
|
||||
let post_padding = self.padding(min - width as u16, Alignment::Right)?;
|
||||
self.buf.write_str(buf)?;
|
||||
post_padding.write(self)?;
|
||||
self.options.fill = old_fill;
|
||||
|
|
@ -1654,7 +1657,7 @@ impl<'a> Formatter<'a> {
|
|||
}
|
||||
// Otherwise, the sign and prefix goes after the padding
|
||||
Some(min) => {
|
||||
let post_padding = self.padding(min - width, Alignment::Right)?;
|
||||
let post_padding = self.padding(min - width as u16, Alignment::Right)?;
|
||||
write_prefix(self, sign, prefix)?;
|
||||
self.buf.write_str(buf)?;
|
||||
post_padding.write(self)
|
||||
|
|
@ -1702,14 +1705,14 @@ impl<'a> Formatter<'a> {
|
|||
// string being formatted.
|
||||
let (s, char_count) = if let Some(max_char_count) = self.options.precision {
|
||||
let mut iter = s.char_indices();
|
||||
let remaining = match iter.advance_by(max_char_count) {
|
||||
let remaining = match iter.advance_by(usize::from(max_char_count)) {
|
||||
Ok(()) => 0,
|
||||
Err(remaining) => remaining.get(),
|
||||
};
|
||||
// SAFETY: The offset of `.char_indices()` is guaranteed to be
|
||||
// in-bounds and between character boundaries.
|
||||
let truncated = unsafe { s.get_unchecked(..iter.offset()) };
|
||||
(truncated, max_char_count - remaining)
|
||||
(truncated, usize::from(max_char_count) - remaining)
|
||||
} else {
|
||||
// Use the optimized char counting algorithm for the full string.
|
||||
(s, s.chars().count())
|
||||
|
|
@ -1717,11 +1720,11 @@ impl<'a> Formatter<'a> {
|
|||
|
||||
// The `width` field is more of a minimum width parameter at this point.
|
||||
if let Some(width) = self.options.width
|
||||
&& char_count < width
|
||||
&& char_count < usize::from(width)
|
||||
{
|
||||
// If we're under the minimum width, then fill up the minimum width
|
||||
// with the specified string + some alignment.
|
||||
let post_padding = self.padding(width - char_count, Alignment::Left)?;
|
||||
let post_padding = self.padding(width - char_count as u16, Alignment::Left)?;
|
||||
self.buf.write_str(s)?;
|
||||
post_padding.write(self)
|
||||
} else {
|
||||
|
|
@ -1737,7 +1740,7 @@ impl<'a> Formatter<'a> {
|
|||
/// thing that is being padded.
|
||||
pub(crate) fn padding(
|
||||
&mut self,
|
||||
padding: usize,
|
||||
padding: u16,
|
||||
default: Alignment,
|
||||
) -> result::Result<PostPadding, Error> {
|
||||
let align = self.align().unwrap_or(default);
|
||||
|
|
@ -1777,19 +1780,19 @@ impl<'a> Formatter<'a> {
|
|||
|
||||
// remove the sign from the formatted parts
|
||||
formatted.sign = "";
|
||||
width = width.saturating_sub(sign.len());
|
||||
width = width.saturating_sub(sign.len() as u16);
|
||||
self.options.fill = '0';
|
||||
self.options.align = Some(Alignment::Right);
|
||||
}
|
||||
|
||||
// remaining parts go through the ordinary padding process.
|
||||
let len = formatted.len();
|
||||
let ret = if width <= len {
|
||||
let ret = if usize::from(width) <= len {
|
||||
// no padding
|
||||
// SAFETY: Per the precondition.
|
||||
unsafe { self.write_formatted_parts(&formatted) }
|
||||
} else {
|
||||
let post_padding = self.padding(width - len, Alignment::Right)?;
|
||||
let post_padding = self.padding(width - len as u16, Alignment::Right)?;
|
||||
// SAFETY: Per the precondition.
|
||||
unsafe {
|
||||
self.write_formatted_parts(&formatted)?;
|
||||
|
|
@ -2021,7 +2024,7 @@ impl<'a> Formatter<'a> {
|
|||
#[must_use]
|
||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||
pub fn width(&self) -> Option<usize> {
|
||||
self.options.width
|
||||
self.options.width.map(|x| x as usize)
|
||||
}
|
||||
|
||||
/// Returns the optionally specified precision for numeric types.
|
||||
|
|
@ -2052,7 +2055,7 @@ impl<'a> Formatter<'a> {
|
|||
#[must_use]
|
||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||
pub fn precision(&self) -> Option<usize> {
|
||||
self.options.precision
|
||||
self.options.precision.map(|x| x as usize)
|
||||
}
|
||||
|
||||
/// Determines if the `+` flag was specified.
|
||||
|
|
@ -2792,7 +2795,7 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul
|
|||
f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
|
||||
|
||||
if f.options.width.is_none() {
|
||||
f.options.width = Some((usize::BITS / 4) as usize + 2);
|
||||
f.options.width = Some((usize::BITS / 4) as u16 + 2);
|
||||
}
|
||||
}
|
||||
f.options.flags |= 1 << (rt::Flag::Alternate as u32);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,11 @@ pub enum Alignment {
|
|||
#[derive(Copy, Clone)]
|
||||
pub enum Count {
|
||||
/// Specified with a literal number, stores the value
|
||||
#[cfg(bootstrap)]
|
||||
Is(usize),
|
||||
/// Specified with a literal number, stores the value
|
||||
#[cfg(not(bootstrap))]
|
||||
Is(u16),
|
||||
/// Specified using `$` and `*` syntaxes, stores the index into `args`
|
||||
Param(usize),
|
||||
/// Not specified
|
||||
|
|
@ -74,7 +78,7 @@ enum ArgumentType<'a> {
|
|||
formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result,
|
||||
_lifetime: PhantomData<&'a ()>,
|
||||
},
|
||||
Count(usize),
|
||||
Count(u16),
|
||||
}
|
||||
|
||||
/// This struct represents a generic "argument" which is taken by format_args!().
|
||||
|
|
@ -151,7 +155,10 @@ impl Argument<'_> {
|
|||
}
|
||||
#[inline]
|
||||
pub const fn from_usize(x: &usize) -> Argument<'_> {
|
||||
Argument { ty: ArgumentType::Count(*x) }
|
||||
if *x > u16::MAX as usize {
|
||||
panic!("Formatting argument out of range");
|
||||
};
|
||||
Argument { ty: ArgumentType::Count(*x as u16) }
|
||||
}
|
||||
|
||||
/// Format this placeholder argument.
|
||||
|
|
@ -181,7 +188,7 @@ impl Argument<'_> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) const fn as_usize(&self) -> Option<usize> {
|
||||
pub(super) const fn as_u16(&self) -> Option<u16> {
|
||||
match self.ty {
|
||||
ArgumentType::Count(count) => Some(count),
|
||||
ArgumentType::Placeholder { .. } => None,
|
||||
|
|
|
|||
|
|
@ -1377,7 +1377,8 @@ impl fmt::Debug for Duration {
|
|||
} else {
|
||||
// We need to add padding. Use the `Formatter::padding` helper function.
|
||||
let default_align = fmt::Alignment::Left;
|
||||
let post_padding = f.padding(requested_w - actual_w, default_align)?;
|
||||
let post_padding =
|
||||
f.padding((requested_w - actual_w) as u16, default_align)?;
|
||||
emit_without_padding(f)?;
|
||||
post_padding.write(f)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -577,7 +577,7 @@ where
|
|||
}
|
||||
|
||||
// very large output
|
||||
assert_eq!(to_string(f, 1.1, Minus, 80000), format!("1.1{:0>79999}", ""));
|
||||
assert_eq!(to_string(f, 1.1, Minus, 50000), format!("1.1{:0>49999}", ""));
|
||||
}
|
||||
|
||||
pub fn to_shortest_exp_str_test<F>(mut f_: F)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue