printf: support precision for integers

This commit is contained in:
Terts Diepraam 2023-11-17 14:42:52 +01:00
parent f83e0d1b04
commit f3da0817a5
2 changed files with 38 additions and 4 deletions

View file

@ -63,6 +63,7 @@ pub enum NumberAlignment {
pub struct SignedInt {
pub width: usize,
pub precision: usize,
pub positive_sign: PositiveSign,
pub alignment: NumberAlignment,
}
@ -79,16 +80,19 @@ impl Formatter for SignedInt {
}?;
}
let s = format!("{:0width$}", x, width = self.precision);
match self.alignment {
NumberAlignment::Left => write!(writer, "{x:<width$}", width = self.width),
NumberAlignment::RightSpace => write!(writer, "{x:>width$}", width = self.width),
NumberAlignment::RightZero => write!(writer, "{x:0>width$}", width = self.width),
NumberAlignment::Left => write!(writer, "{s:<width$}", width = self.width),
NumberAlignment::RightSpace => write!(writer, "{s:>width$}", width = self.width),
NumberAlignment::RightZero => write!(writer, "{s:0>width$}", width = self.width),
}
}
fn try_from_spec(s: Spec) -> Result<Self, FormatError> {
let Spec::SignedInt {
width,
precision,
positive_sign,
alignment,
} = s
@ -102,8 +106,15 @@ impl Formatter for SignedInt {
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
};
let precision = match precision {
Some(CanAsterisk::Fixed(x)) => x,
None => 0,
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
};
Ok(Self {
width,
precision,
positive_sign,
alignment,
})
@ -113,6 +124,7 @@ impl Formatter for SignedInt {
pub struct UnsignedInt {
pub variant: UnsignedIntVariant,
pub width: usize,
pub precision: usize,
pub alignment: NumberAlignment,
}
@ -120,7 +132,7 @@ impl Formatter for UnsignedInt {
type Input = u64;
fn fmt(&self, mut writer: impl Write, x: Self::Input) -> std::io::Result<()> {
let s = match self.variant {
let mut s = match self.variant {
UnsignedIntVariant::Decimal => format!("{x}"),
UnsignedIntVariant::Octal(Prefix::No) => format!("{x:o}"),
UnsignedIntVariant::Octal(Prefix::Yes) => format!("{x:#o}"),
@ -138,6 +150,10 @@ impl Formatter for UnsignedInt {
}
};
if self.precision > s.len() {
s = format!("{:0width$}", s, width = self.precision)
}
match self.alignment {
NumberAlignment::Left => write!(writer, "{s:<width$}", width = self.width),
NumberAlignment::RightSpace => write!(writer, "{s:>width$}", width = self.width),
@ -149,6 +165,7 @@ impl Formatter for UnsignedInt {
let Spec::UnsignedInt {
variant,
width,
precision,
alignment,
} = s
else {
@ -161,8 +178,15 @@ impl Formatter for UnsignedInt {
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
};
let precision = match precision {
Some(CanAsterisk::Fixed(x)) => x,
None => 0,
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
};
Ok(Self {
width,
precision,
variant,
alignment,
})

View file

@ -22,12 +22,14 @@ pub enum Spec {
},
SignedInt {
width: Option<CanAsterisk<usize>>,
precision: Option<CanAsterisk<usize>>,
positive_sign: PositiveSign,
alignment: NumberAlignment,
},
UnsignedInt {
variant: UnsignedIntVariant,
width: Option<CanAsterisk<usize>>,
precision: Option<CanAsterisk<usize>>,
alignment: NumberAlignment,
},
Float {
@ -167,6 +169,7 @@ impl Spec {
},
b'd' | b'i' => Spec::SignedInt {
width,
precision,
alignment: match (minus, zero) {
(true, _) => NumberAlignment::Left,
(false, true) => NumberAlignment::RightZero,
@ -197,6 +200,7 @@ impl Spec {
};
Spec::UnsignedInt {
variant,
precision,
width,
alignment,
}
@ -282,10 +286,12 @@ impl Spec {
}
&Spec::SignedInt {
width,
precision,
positive_sign,
alignment,
} => {
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
let precision = resolve_asterisk(precision, &mut args)?.unwrap_or(0);
let arg = next_arg(&mut args)?;
let Some(i) = arg.get_i64() else {
@ -294,6 +300,7 @@ impl Spec {
num_format::SignedInt {
width,
precision,
positive_sign,
alignment,
}
@ -303,9 +310,11 @@ impl Spec {
&Spec::UnsignedInt {
variant,
width,
precision,
alignment,
} => {
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
let precision = resolve_asterisk(precision, &mut args)?.unwrap_or(0);
let arg = next_arg(args)?;
let Some(i) = arg.get_u64() else {
@ -314,6 +323,7 @@ impl Spec {
num_format::UnsignedInt {
variant,
precision,
width,
alignment,
}