@@ -6,7 +6,7 @@ use std::path::PathBuf;
66use std:: sync:: atomic:: { AtomicBool , Ordering } ;
77use std:: sync:: { Arc , Mutex , MutexGuard } ;
88use std:: thread;
9- use std:: time:: { Duration , Instant } ;
9+ use std:: time:: { Duration , Instant , SystemTime } ;
1010
1111use anyhow:: { Result , anyhow} ;
1212use crossbeam_channel:: { Receiver , RecvTimeoutError , SendError , Sender , bounded} ;
@@ -675,37 +675,45 @@ impl WorkerState {
675675}
676676
677677fn sort_worker_results ( results : & mut [ WorkerResult ] , sort_key : SortKey ) {
678- results. sort_by ( |a, b| {
679- // Errors sort to the end; two errors are considered equal.
680- let ( a, b) = match ( a, b) {
681- ( WorkerResult :: Entry ( a) , WorkerResult :: Entry ( b) ) => ( a, b) ,
682- ( WorkerResult :: Error ( _) , WorkerResult :: Entry ( _) ) => {
683- return std:: cmp:: Ordering :: Greater ;
684- }
685- ( WorkerResult :: Entry ( _) , WorkerResult :: Error ( _) ) => {
686- return std:: cmp:: Ordering :: Less ;
687- }
688- ( WorkerResult :: Error ( _) , WorkerResult :: Error ( _) ) => {
689- return std:: cmp:: Ordering :: Equal ;
690- }
691- } ;
678+ // Build the key extractor once, based on sort_key.
679+ // Returns None for errors, pushing them to the end naturally via Ord on Option.
680+ let key_fn: Box < dyn Fn ( & WorkerResult ) -> Option < SortKeyValue > > = match sort_key {
681+ SortKey :: Path => Box :: new ( |r| match r {
682+ WorkerResult :: Entry ( e) => Some ( SortKeyValue :: Path ( e. path ( ) . to_path_buf ( ) ) ) ,
683+ WorkerResult :: Error ( _) => None ,
684+ } ) ,
685+ SortKey :: Size => Box :: new ( |r| match r {
686+ WorkerResult :: Entry ( e) => Some ( SortKeyValue :: Size (
687+ e. metadata ( ) . map ( |m| m. len ( ) ) . unwrap_or ( 0 ) ,
688+ ) ) ,
689+ WorkerResult :: Error ( _) => None ,
690+ } ) ,
691+ SortKey :: Created => Box :: new ( |r| match r {
692+ WorkerResult :: Entry ( e) => Some ( SortKeyValue :: Time (
693+ e. metadata ( ) . and_then ( |m| m. created ( ) . ok ( ) ) ,
694+ ) ) ,
695+ WorkerResult :: Error ( _) => None ,
696+ } ) ,
697+ SortKey :: Modified => Box :: new ( |r| match r {
698+ WorkerResult :: Entry ( e) => Some ( SortKeyValue :: Time (
699+ e. metadata ( ) . and_then ( |m| m. modified ( ) . ok ( ) ) ,
700+ ) ) ,
701+ WorkerResult :: Error ( _) => None ,
702+ } ) ,
703+ } ;
704+
705+ // Use sort_by_cached_key to avoid recomputing the key for each comparison.
706+ results. sort_by_cached_key ( |r| key_fn ( r) ) ;
707+ }
692708
693- match sort_key {
694- SortKey :: Path => a. path ( ) . cmp ( b. path ( ) ) ,
695- SortKey :: Size => {
696- let size = |e : & DirEntry | e. metadata ( ) . map ( |m| m. len ( ) ) . unwrap_or ( 0 ) ;
697- size ( a) . cmp ( & size ( b) )
698- }
699- SortKey :: Created => {
700- let time = |e : & DirEntry | e. metadata ( ) . and_then ( |m| m. created ( ) . ok ( ) ) ;
701- time ( a) . cmp ( & time ( b) )
702- }
703- SortKey :: Modified => {
704- let time = |e : & DirEntry | e. metadata ( ) . and_then ( |m| m. modified ( ) . ok ( ) ) ;
705- time ( a) . cmp ( & time ( b) )
706- }
707- }
708- } ) ;
709+ /// Comparable key values, one variant per SortKey.
710+ /// None sorts last via Option<T: Ord>'s natural ordering (None > Some).
711+ /// Only like enum variants will be compared (e.g., Path < Size will never be compared).
712+ #[ derive( Eq , PartialEq , Ord , PartialOrd ) ]
713+ enum SortKeyValue {
714+ Path ( PathBuf ) ,
715+ Size ( u64 ) ,
716+ Time ( Option < SystemTime > ) ,
709717}
710718
711719fn search_str_for_entry < ' a > (
0 commit comments