@@ -316,7 +316,7 @@ impl Spec {
316316 match self {
317317 Self :: Char { width, align_left } => {
318318 let ( width, neg_width) =
319- resolve_asterisk_maybe_negative ( * width, & mut args) . unwrap_or_default ( ) ;
319+ resolve_asterisk_width ( * width, & mut args) . unwrap_or_default ( ) ;
320320 write_padded ( writer, & [ args. get_char ( ) ] , width, * align_left || neg_width)
321321 }
322322 Self :: String {
@@ -325,15 +325,15 @@ impl Spec {
325325 precision,
326326 } => {
327327 let ( width, neg_width) =
328- resolve_asterisk_maybe_negative ( * width, & mut args) . unwrap_or_default ( ) ;
328+ resolve_asterisk_width ( * width, & mut args) . unwrap_or_default ( ) ;
329329
330330 // GNU does do this truncation on a byte level, see for instance:
331331 // printf "%.1s" 🙃
332332 // > �
333333 // For now, we let printf panic when we truncate within a code point.
334334 // TODO: We need to not use Rust's formatting for aligning the output,
335335 // so that we can just write bytes to stdout without panicking.
336- let precision = resolve_asterisk ( * precision, & mut args) ;
336+ let precision = resolve_asterisk_precision ( * precision, & mut args) ;
337337 let s = args. get_str ( ) ;
338338 let truncated = match precision {
339339 Some ( p) if p < s. len ( ) => & s[ ..p] ,
@@ -349,7 +349,7 @@ impl Spec {
349349 Self :: EscapedString => {
350350 let s = args. get_str ( ) ;
351351 let mut parsed = Vec :: new ( ) ;
352- for c in parse_escape_only ( s. as_bytes ( ) , OctalParsing :: default ( ) ) {
352+ for c in parse_escape_only ( s. as_bytes ( ) , OctalParsing :: ThreeDigits ) {
353353 match c. write ( & mut parsed) ? {
354354 ControlFlow :: Continue ( ( ) ) => { }
355355 ControlFlow :: Break ( ( ) ) => {
@@ -382,8 +382,10 @@ impl Spec {
382382 positive_sign,
383383 alignment,
384384 } => {
385- let width = resolve_asterisk ( * width, & mut args) . unwrap_or ( 0 ) ;
386- let precision = resolve_asterisk ( * precision, & mut args) . unwrap_or ( 0 ) ;
385+ let ( width, neg_width) =
386+ resolve_asterisk_width ( * width, & mut args) . unwrap_or ( ( 0 , false ) ) ;
387+ let precision =
388+ resolve_asterisk_precision ( * precision, & mut args) . unwrap_or_default ( ) ;
387389 let i = args. get_i64 ( ) ;
388390
389391 if precision as u64 > i32:: MAX as u64 {
@@ -394,7 +396,11 @@ impl Spec {
394396 width,
395397 precision,
396398 positive_sign : * positive_sign,
397- alignment : * alignment,
399+ alignment : if neg_width {
400+ NumberAlignment :: Left
401+ } else {
402+ * alignment
403+ } ,
398404 }
399405 . fmt ( writer, i)
400406 . map_err ( FormatError :: IoError )
@@ -405,8 +411,10 @@ impl Spec {
405411 precision,
406412 alignment,
407413 } => {
408- let width = resolve_asterisk ( * width, & mut args) . unwrap_or ( 0 ) ;
409- let precision = resolve_asterisk ( * precision, & mut args) . unwrap_or ( 0 ) ;
414+ let ( width, neg_width) =
415+ resolve_asterisk_width ( * width, & mut args) . unwrap_or ( ( 0 , false ) ) ;
416+ let precision =
417+ resolve_asterisk_precision ( * precision, & mut args) . unwrap_or_default ( ) ;
410418 let i = args. get_u64 ( ) ;
411419
412420 if precision as u64 > i32:: MAX as u64 {
@@ -417,7 +425,11 @@ impl Spec {
417425 variant : * variant,
418426 precision,
419427 width,
420- alignment : * alignment,
428+ alignment : if neg_width {
429+ NumberAlignment :: Left
430+ } else {
431+ * alignment
432+ } ,
421433 }
422434 . fmt ( writer, i)
423435 . map_err ( FormatError :: IoError )
@@ -431,8 +443,9 @@ impl Spec {
431443 alignment,
432444 precision,
433445 } => {
434- let width = resolve_asterisk ( * width, & mut args) . unwrap_or ( 0 ) ;
435- let precision = resolve_asterisk ( * precision, & mut args) . unwrap_or ( 6 ) ;
446+ let ( width, neg_width) =
447+ resolve_asterisk_width ( * width, & mut args) . unwrap_or ( ( 0 , false ) ) ;
448+ let precision = resolve_asterisk_precision ( * precision, & mut args) . unwrap_or ( 6 ) ;
436449 let f: ExtendedBigDecimal = args. get_extended_big_decimal ( ) ;
437450
438451 if precision as u64 > i32:: MAX as u64 {
@@ -446,7 +459,11 @@ impl Spec {
446459 case : * case,
447460 force_decimal : * force_decimal,
448461 positive_sign : * positive_sign,
449- alignment : * alignment,
462+ alignment : if neg_width {
463+ NumberAlignment :: Left
464+ } else {
465+ * alignment
466+ } ,
450467 }
451468 . fmt ( writer, & f)
452469 . map_err ( FormatError :: IoError )
@@ -455,18 +472,7 @@ impl Spec {
455472 }
456473}
457474
458- fn resolve_asterisk < ' a > (
459- option : Option < CanAsterisk < usize > > ,
460- mut args : impl ArgumentIter < ' a > ,
461- ) -> Option < usize > {
462- match option {
463- None => None ,
464- Some ( CanAsterisk :: Asterisk ) => Some ( usize:: try_from ( args. get_u64 ( ) ) . ok ( ) . unwrap_or ( 0 ) ) ,
465- Some ( CanAsterisk :: Fixed ( w) ) => Some ( w) ,
466- }
467- }
468-
469- fn resolve_asterisk_maybe_negative < ' a > (
475+ fn resolve_asterisk_width < ' a > (
470476 option : Option < CanAsterisk < usize > > ,
471477 mut args : impl ArgumentIter < ' a > ,
472478) -> Option < ( usize , bool ) > {
@@ -484,6 +490,21 @@ fn resolve_asterisk_maybe_negative<'a>(
484490 }
485491}
486492
493+ fn resolve_asterisk_precision < ' a > (
494+ option : Option < CanAsterisk < usize > > ,
495+ mut args : impl ArgumentIter < ' a > ,
496+ ) -> Option < usize > {
497+ match option {
498+ None => None ,
499+ Some ( CanAsterisk :: Asterisk ) => match args. get_i64 ( ) {
500+ v if v >= 0 => usize:: try_from ( v) . ok ( ) ,
501+ v if v < 0 => Some ( 0usize ) ,
502+ _ => None ,
503+ } ,
504+ Some ( CanAsterisk :: Fixed ( w) ) => Some ( w) ,
505+ }
506+ }
507+
487508fn write_padded (
488509 mut writer : impl Write ,
489510 text : & [ u8 ] ,
0 commit comments