@@ -314,29 +314,36 @@ impl Spec {
314314 ) -> Result < ( ) , FormatError > {
315315 match self {
316316 Self :: Char { width, align_left } => {
317- let width = resolve_asterisk ( * width, & mut args) ?. unwrap_or ( 0 ) ;
318- write_padded ( writer, & [ args. get_char ( ) ] , width, * align_left)
317+ let ( width, neg_width) =
318+ resolve_asterisk_maybe_negative ( * width, & mut args) . unwrap_or_default ( ) ;
319+ write_padded ( writer, & [ args. get_char ( ) ] , width, * align_left || neg_width)
319320 }
320321 Self :: String {
321322 width,
322323 align_left,
323324 precision,
324325 } => {
325- let width = resolve_asterisk ( * width, & mut args) ?. unwrap_or ( 0 ) ;
326+ let ( width, neg_width) =
327+ resolve_asterisk_maybe_negative ( * width, & mut args) . unwrap_or_default ( ) ;
326328
327329 // GNU does do this truncation on a byte level, see for instance:
328330 // printf "%.1s" 🙃
329331 // > �
330332 // For now, we let printf panic when we truncate within a code point.
331333 // TODO: We need to not use Rust's formatting for aligning the output,
332334 // so that we can just write bytes to stdout without panicking.
333- let precision = resolve_asterisk ( * precision, & mut args) ? ;
335+ let precision = resolve_asterisk ( * precision, & mut args) ;
334336 let s = args. get_str ( ) ;
335337 let truncated = match precision {
336338 Some ( p) if p < s. len ( ) => & s[ ..p] ,
337339 _ => s,
338340 } ;
339- write_padded ( writer, truncated. as_bytes ( ) , width, * align_left)
341+ write_padded (
342+ writer,
343+ truncated. as_bytes ( ) ,
344+ width,
345+ * align_left || neg_width,
346+ )
340347 }
341348 Self :: EscapedString => {
342349 let s = args. get_str ( ) ;
@@ -374,8 +381,8 @@ impl Spec {
374381 positive_sign,
375382 alignment,
376383 } => {
377- let width = resolve_asterisk ( * width, & mut args) ? . unwrap_or ( 0 ) ;
378- let precision = resolve_asterisk ( * precision, & mut args) ? . unwrap_or ( 0 ) ;
384+ let width = resolve_asterisk ( * width, & mut args) . unwrap_or ( 0 ) ;
385+ let precision = resolve_asterisk ( * precision, & mut args) . unwrap_or ( 0 ) ;
379386 let i = args. get_i64 ( ) ;
380387
381388 if precision as u64 > i32:: MAX as u64 {
@@ -397,8 +404,8 @@ impl Spec {
397404 precision,
398405 alignment,
399406 } => {
400- let width = resolve_asterisk ( * width, & mut args) ? . unwrap_or ( 0 ) ;
401- let precision = resolve_asterisk ( * precision, & mut args) ? . unwrap_or ( 0 ) ;
407+ let width = resolve_asterisk ( * width, & mut args) . unwrap_or ( 0 ) ;
408+ let precision = resolve_asterisk ( * precision, & mut args) . unwrap_or ( 0 ) ;
402409 let i = args. get_u64 ( ) ;
403410
404411 if precision as u64 > i32:: MAX as u64 {
@@ -423,8 +430,8 @@ impl Spec {
423430 alignment,
424431 precision,
425432 } => {
426- let width = resolve_asterisk ( * width, & mut args) ? . unwrap_or ( 0 ) ;
427- let precision = resolve_asterisk ( * precision, & mut args) ? . unwrap_or ( 6 ) ;
433+ let width = resolve_asterisk ( * width, & mut args) . unwrap_or ( 0 ) ;
434+ let precision = resolve_asterisk ( * precision, & mut args) . unwrap_or ( 6 ) ;
428435 let f = args. get_f64 ( ) ;
429436
430437 if precision as u64 > i32:: MAX as u64 {
@@ -450,12 +457,30 @@ impl Spec {
450457fn resolve_asterisk < ' a > (
451458 option : Option < CanAsterisk < usize > > ,
452459 mut args : impl ArgumentIter < ' a > ,
453- ) -> Result < Option < usize > , FormatError > {
454- Ok ( match option {
460+ ) -> Option < usize > {
461+ match option {
455462 None => None ,
456463 Some ( CanAsterisk :: Asterisk ) => Some ( usize:: try_from ( args. get_u64 ( ) ) . ok ( ) . unwrap_or ( 0 ) ) ,
457464 Some ( CanAsterisk :: Fixed ( w) ) => Some ( w) ,
458- } )
465+ }
466+ }
467+
468+ fn resolve_asterisk_maybe_negative < ' a > (
469+ option : Option < CanAsterisk < usize > > ,
470+ mut args : impl ArgumentIter < ' a > ,
471+ ) -> Option < ( usize , bool ) > {
472+ match option {
473+ None => None ,
474+ Some ( CanAsterisk :: Asterisk ) => {
475+ let nb = args. get_i64 ( ) ;
476+ if nb < 0 {
477+ Some ( ( usize:: try_from ( -( nb as isize ) ) . ok ( ) . unwrap_or ( 0 ) , true ) )
478+ } else {
479+ Some ( ( usize:: try_from ( nb) . ok ( ) . unwrap_or ( 0 ) , false ) )
480+ }
481+ }
482+ Some ( CanAsterisk :: Fixed ( w) ) => Some ( ( w, false ) ) ,
483+ }
459484}
460485
461486fn write_padded (
0 commit comments