Skip to content

Commit

Permalink
Make sort order deterministic when sizes match
Browse files Browse the repository at this point in the history
  • Loading branch information
emilevr committed Nov 27, 2023
1 parent 1b6f2f6 commit 448173a
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 10 deletions.
9 changes: 7 additions & 2 deletions src/directory_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl DirectoryItem {

// Then we sort.
if child_count > 1 {
self.children.par_sort_by(|a, b| b.partial_cmp(a).unwrap());
self.children.par_sort_by(|a, b| a.cmp(b));
}

// Update our own count and size from our descendants' stats.
Expand All @@ -227,7 +227,12 @@ impl DirectoryItem {
impl Ord for DirectoryItem {
#[inline(always)]
fn cmp(&self, other: &Self) -> Ordering {
self.size_in_bytes.cmp(&other.size_in_bytes)
// We want the ordering to be descending by size, so we swap the operands.
if self.size_in_bytes == other.size_in_bytes {
self.path_segment.cmp(&other.path_segment)
} else {
other.size_in_bytes.cmp(&self.size_in_bytes)
}
}
}

Expand Down
24 changes: 16 additions & 8 deletions src/directory_item_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use std::{cmp::Ordering, path::PathBuf};
use uuid::Uuid;

#[rstest]
#[case(123, 123, Ordering::Equal)]
#[case(1, 2, Ordering::Less)]
#[case(2, 1, Ordering::Greater)]
fn cmp_with_given_size_in_bytes_returns_correct_ordering(
#[case(123, 123, Ordering::Less)]
#[case(1, 2, Ordering::Greater)]
#[case(2, 1, Ordering::Less)]
fn cmp_with_given_size_in_bytes_returns_descending_ordering(
#[case] size_in_bytes_1: u64,
#[case] size_in_bytes_2: u64,
#[case] expected_ordering: Ordering,
Expand Down Expand Up @@ -47,10 +47,10 @@ fn cmp_with_given_size_in_bytes_returns_correct_ordering(
}

#[rstest]
#[case(432, 432, Some(Ordering::Equal))]
#[case(1, 7, Some(Ordering::Less))]
#[case(99, 98, Some(Ordering::Greater))]
fn partial_cmp_with_given_size_in_bytes_returns_correct_ordering(
#[case(432, 432, Some(Ordering::Less))]
#[case(1, 7, Some(Ordering::Greater))]
#[case(99, 98, Some(Ordering::Less))]
fn partial_cmp_with_given_size_in_bytes_returns_descending_ordering(
#[case] size_in_bytes_1: u64,
#[case] size_in_bytes_2: u64,
#[case] expected_ordering: Option<Ordering>,
Expand Down Expand Up @@ -81,6 +81,10 @@ fn partial_cmp_with_given_size_in_bytes_returns_correct_ordering(
let ordering = v1.partial_cmp(&v2);

// Assert
println!(
"v1 size = {} bytes, v2 size = {} bytes",
v1.size_in_bytes, v2.size_in_bytes
);
assert_eq!(expected_ordering, ordering);
}

Expand Down Expand Up @@ -119,6 +123,10 @@ fn eq_with_given_size_in_bytes_returns_correct_result(
let equal = v1.eq(&v2);

// Assert
println!(
"v1 size = {} bytes, v2 size = {} bytes",
v1.size_in_bytes, v2.size_in_bytes
);
assert_eq!(expected_result, equal);
}

Expand Down
8 changes: 8 additions & 0 deletions src/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#[path = "./size_test.rs"]
mod size_test;

use std::fmt::Display;

#[cfg(feature = "cli")]
use clap::ValueEnum;

Expand Down Expand Up @@ -110,6 +112,12 @@ impl Size {
}
}

impl Display for Size {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} bytes", self.value)
}
}

impl From<Size> for u64 {
#[inline]
fn from(value: Size) -> Self {
Expand Down

0 comments on commit 448173a

Please sign in to comment.