@@ -38,21 +38,30 @@ use jiff::fmt::strtime::{BrokenDownTime, Config, PosixCustom};
3838use regex:: Regex ;
3939use std:: fmt;
4040use std:: sync:: OnceLock ;
41+ use uucore:: translate;
4142
4243/// Error type for format modifier operations
4344#[ derive( Debug ) ]
4445pub enum FormatError {
4546 /// Error from the underlying jiff library
4647 JiffError ( jiff:: Error ) ,
47- /// Custom error message
48- Custom ( String ) ,
48+ /// Field width calculation overflowed or required allocation failed
49+ FieldWidthTooLarge { width : usize , specifier : String } ,
4950}
5051
5152impl fmt:: Display for FormatError {
5253 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
5354 match self {
5455 Self :: JiffError ( e) => write ! ( f, "{e}" ) ,
55- Self :: Custom ( s) => write ! ( f, "{s}" ) ,
56+ Self :: FieldWidthTooLarge { width, specifier } => write ! (
57+ f,
58+ "{}" ,
59+ translate!(
60+ "date-error-format-modifier-width-too-large" ,
61+ "width" => width,
62+ "specifier" => specifier
63+ )
64+ ) ,
5665 }
5766 }
5867}
@@ -63,12 +72,6 @@ impl From<jiff::Error> for FormatError {
6372 }
6473}
6574
66- const ERR_FIELD_WIDTH_TOO_LARGE : & str = "field width too large" ;
67-
68- fn width_too_large_error ( ) -> FormatError {
69- FormatError :: Custom ( ERR_FIELD_WIDTH_TOO_LARGE . to_string ( ) )
70- }
71-
7275/// Regex to match format specifiers with optional modifiers
7376/// Pattern: % \[flags\] \[width\] specifier
7477/// Flags: -, _, 0, ^, #, +
@@ -392,28 +395,38 @@ fn apply_modifiers(
392395 // Zero padding: sign first, then zeros (e.g., "-0022")
393396 let sign = result. chars ( ) . next ( ) . unwrap ( ) ;
394397 let rest = & result[ 1 ..] ;
395- let target_len = result
396- . len ( )
397- . checked_add ( padding)
398- . ok_or_else ( width_too_large_error) ?;
398+ let target_len = result. len ( ) . checked_add ( padding) . ok_or_else ( || {
399+ FormatError :: FieldWidthTooLarge {
400+ width,
401+ specifier : specifier. to_string ( ) ,
402+ }
403+ } ) ?;
399404 let mut padded = String :: new ( ) ;
400405 padded
401406 . try_reserve ( target_len)
402- . map_err ( |_| width_too_large_error ( ) ) ?;
407+ . map_err ( |_| FormatError :: FieldWidthTooLarge {
408+ width,
409+ specifier : specifier. to_string ( ) ,
410+ } ) ?;
403411 padded. push ( sign) ;
404412 padded. extend ( std:: iter:: repeat_n ( '0' , padding) ) ;
405413 padded. push_str ( rest) ;
406414 result = padded;
407415 } else {
408416 // Default: pad on the left (e.g., " -22" or " 1999")
409- let target_len = result
410- . len ( )
411- . checked_add ( padding)
412- . ok_or_else ( width_too_large_error) ?;
417+ let target_len = result. len ( ) . checked_add ( padding) . ok_or_else ( || {
418+ FormatError :: FieldWidthTooLarge {
419+ width,
420+ specifier : specifier. to_string ( ) ,
421+ }
422+ } ) ?;
413423 let mut padded = String :: new ( ) ;
414424 padded
415425 . try_reserve ( target_len)
416- . map_err ( |_| width_too_large_error ( ) ) ?;
426+ . map_err ( |_| FormatError :: FieldWidthTooLarge {
427+ width,
428+ specifier : specifier. to_string ( ) ,
429+ } ) ?;
417430 padded. extend ( std:: iter:: repeat_n ( pad_char, padding) ) ;
418431 padded. push_str ( & result) ;
419432 result = padded;
@@ -775,7 +788,8 @@ mod tests {
775788 let err = apply_modifiers ( "x" , "" , usize:: MAX , "c" , true ) . unwrap_err ( ) ;
776789 assert ! ( matches!(
777790 err,
778- FormatError :: Custom ( message) if message == ERR_FIELD_WIDTH_TOO_LARGE
791+ FormatError :: FieldWidthTooLarge { width, specifier }
792+ if width == usize :: MAX && specifier == "c"
779793 ) ) ;
780794 }
781795}
0 commit comments