@@ -1415,7 +1415,11 @@ impl<'a> Formatter<'a> {
14151415 /// Takes the formatted parts and applies the padding.
14161416 /// Assumes that the caller already has rendered the parts with required precision,
14171417 /// so that `self.precision` can be ignored.
1418- fn pad_formatted_parts ( & mut self , formatted : & numfmt:: Formatted < ' _ > ) -> Result {
1418+ ///
1419+ /// # Safety
1420+ ///
1421+ /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
1422+ unsafe fn pad_formatted_parts ( & mut self , formatted : & numfmt:: Formatted < ' _ > ) -> Result {
14191423 if let Some ( mut width) = self . width {
14201424 // for the sign-aware zero padding, we render the sign first and
14211425 // behave as if we had no sign from the beginning.
@@ -1438,31 +1442,35 @@ impl<'a> Formatter<'a> {
14381442 let len = formatted. len ( ) ;
14391443 let ret = if width <= len {
14401444 // no padding
1441- self . write_formatted_parts ( & formatted)
1445+ // SAFETY: Per the precondition.
1446+ unsafe { self . write_formatted_parts ( & formatted) }
14421447 } else {
14431448 let post_padding = self . padding ( width - len, Alignment :: Right ) ?;
1444- self . write_formatted_parts ( & formatted) ?;
1449+ // SAFETY: Per the precondition.
1450+ unsafe {
1451+ self . write_formatted_parts ( & formatted) ?;
1452+ }
14451453 post_padding. write ( self )
14461454 } ;
14471455 self . fill = old_fill;
14481456 self . align = old_align;
14491457 ret
14501458 } else {
14511459 // this is the common case and we take a shortcut
1452- self . write_formatted_parts ( formatted)
1460+ // SAFETY: Per the precondition.
1461+ unsafe { self . write_formatted_parts ( formatted) }
14531462 }
14541463 }
14551464
1456- fn write_formatted_parts ( & mut self , formatted : & numfmt:: Formatted < ' _ > ) -> Result {
1457- fn write_bytes ( buf : & mut dyn Write , s : & [ u8 ] ) -> Result {
1465+ /// # Safety
1466+ ///
1467+ /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
1468+ unsafe fn write_formatted_parts ( & mut self , formatted : & numfmt:: Formatted < ' _ > ) -> Result {
1469+ unsafe fn write_bytes ( buf : & mut dyn Write , s : & [ u8 ] ) -> Result {
14581470 // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`.
14591471 // It's safe to use for `numfmt::Part::Num` since every char `c` is between
1460- // `b'0'` and `b'9'`, which means `s` is valid UTF-8.
1461- // It's also probably safe in practice to use for `numfmt::Part::Copy(buf)`
1462- // since `buf` should be plain ASCII, but it's possible for someone to pass
1463- // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a
1464- // public function.
1465- // FIXME: Determine whether this could result in UB.
1472+ // `b'0'` and `b'9'`, which means `s` is valid UTF-8. It's safe to use for
1473+ // `numfmt::Part::Copy` due to this function's precondition.
14661474 buf. write_str ( unsafe { str:: from_utf8_unchecked ( s) } )
14671475 }
14681476
@@ -1489,11 +1497,15 @@ impl<'a> Formatter<'a> {
14891497 * c = b'0' + ( v % 10 ) as u8 ;
14901498 v /= 10 ;
14911499 }
1492- write_bytes ( self . buf , & s[ ..len] ) ?;
1500+ // SAFETY: Per the precondition.
1501+ unsafe {
1502+ write_bytes ( self . buf , & s[ ..len] ) ?;
1503+ }
14931504 }
1494- numfmt:: Part :: Copy ( buf) => {
1505+ // SAFETY: Per the precondition.
1506+ numfmt:: Part :: Copy ( buf) => unsafe {
14951507 write_bytes ( self . buf , buf) ?;
1496- }
1508+ } ,
14971509 }
14981510 }
14991511 Ok ( ( ) )
0 commit comments