@@ -60,8 +60,6 @@ const UNICODE_REPLACEMENT: char = '\u{FFFD}';
6060struct Settings {
6161 utc : bool ,
6262 format : Format ,
63- /// Raw format bytes for Custom format, to preserve non-UTF-8 bytes in output
64- format_raw : Option < Vec < u8 > > ,
6563 date_source : DateSource ,
6664 set_to : Option < Zoned > ,
6765 debug : bool ,
@@ -91,7 +89,11 @@ enum Format {
9189 Rfc5322 ,
9290 Rfc3339 ( Rfc3339Format ) ,
9391 Resolution ,
94- Custom ( String ) ,
92+ /// A user-supplied format string (after stripping the leading `+`).
93+ /// The `String` is a lossy-UTF-8 copy used by strftime; the optional
94+ /// `Vec<u8>` holds the original bytes when they contained non-UTF-8
95+ /// sequences, so that those bytes can be restored in the output.
96+ Custom ( String , Option < Vec < u8 > > ) ,
9597 Default ,
9698}
9799
@@ -323,7 +325,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
323325 }
324326 }
325327
326- let mut format_raw: Option < Vec < u8 > > = None ;
327328 let format = if let Some ( form) = matches. get_one :: < OsString > ( OPT_FORMAT ) {
328329 let raw_bytes = form. as_encoded_bytes ( ) ;
329330 if raw_bytes. first ( ) != Some ( & b'+' ) {
@@ -344,11 +345,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
344345 ) ) ;
345346 }
346347 let bytes_after_plus = & raw_bytes[ 1 ..] ;
347- if std:: str:: from_utf8 ( bytes_after_plus) . is_err ( ) {
348- format_raw = Some ( bytes_after_plus. to_vec ( ) ) ;
349- }
348+ let format_raw = if std:: str:: from_utf8 ( bytes_after_plus) . is_err ( ) {
349+ Some ( bytes_after_plus. to_vec ( ) )
350+ } else {
351+ None
352+ } ;
350353 let form = String :: from_utf8_lossy ( bytes_after_plus) . into_owned ( ) ;
351- Format :: Custom ( form)
354+ Format :: Custom ( form, format_raw )
352355 } else if let Some ( fmt) = matches
353356 . get_many :: < String > ( OPT_ISO_8601 )
354357 . map ( |mut iter| iter. next ( ) . unwrap_or ( & DATE . to_string ( ) ) . as_str ( ) . into ( ) )
@@ -394,7 +397,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
394397 let settings = Settings {
395398 utc,
396399 format,
397- format_raw,
398400 date_source,
399401 set_to,
400402 debug : debug_mode,
@@ -561,7 +563,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
561563 // Pre-extract non-UTF-8 chunks from the raw format bytes (if any).
562564 // from_utf8_lossy emits one U+FFFD per ill-formed subsequence (WTF-8 spec),
563565 // so we can match them 1:1 when restoring original bytes in the output.
564- let raw_chunks: Option < Vec < & [ u8 ] > > = settings. format_raw . as_ref ( ) . map ( |raw| {
566+ let format_raw_ref = match & settings. format {
567+ Format :: Custom ( _, Some ( raw) ) => Some ( raw) ,
568+ _ => None ,
569+ } ;
570+ let raw_chunks: Option < Vec < & [ u8 ] > > = format_raw_ref. map ( |raw| {
565571 let mut chunks = Vec :: new ( ) ;
566572 let mut i = 0 ;
567573 while i < raw. len ( ) {
@@ -812,7 +818,7 @@ fn make_format_string(settings: &Settings) -> &str {
812818 Rfc3339Format :: Ns => "%F %T.%N%:z" ,
813819 } ,
814820 Format :: Resolution => "%s.%N" ,
815- Format :: Custom ( ref fmt) => fmt,
821+ Format :: Custom ( ref fmt, _ ) => fmt,
816822 Format :: Default => locale:: get_locale_default_format ( ) ,
817823 }
818824}
0 commit comments