Skip to content

Commit

Permalink
feat: Add Array::sort_by
Browse files Browse the repository at this point in the history
`Array::sort_by_key` can't really use a borrowed key because it will be
shuffling things around.  As an alternative, we can just provide the
`cmp` to use.

Fixes #639
  • Loading branch information
epage committed Oct 27, 2023
1 parent ef689bc commit ddadd45
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
30 changes: 30 additions & 0 deletions crates/toml_edit/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,36 @@ impl Array {
.retain(|item| item.as_value().map(&mut keep).unwrap_or(false));
}

/// Sorts the slice with a comparator function.
///
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case.
///
/// The comparator function must define a total ordering for the elements in the slice. If
/// the ordering is not total, the order of the elements is unspecified. An order is a
/// total order if it is (for all `a`, `b` and `c`):
///
/// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and
/// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
/// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use
/// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.
#[inline]
pub fn sort_by<F>(&mut self, mut compare: F)
where
F: FnMut(&Value, &Value) -> std::cmp::Ordering,
{
self.values.sort_by(move |lhs, rhs| {
let lhs = lhs.as_value();
let rhs = rhs.as_value();
match (lhs, rhs) {
(None, None) => std::cmp::Ordering::Equal,
(Some(_), None) => std::cmp::Ordering::Greater,
(None, Some(_)) => std::cmp::Ordering::Less,
(Some(lhs), Some(rhs)) => compare(lhs, rhs),
}
})
}

/// Sorts the array with a key extraction function.
///
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
Expand Down
7 changes: 7 additions & 0 deletions crates/toml_edit/tests/testsuite/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,3 +853,10 @@ src.git = "https://github.com/nixos/nixpkgs"
"#,
);
}

#[test]
fn sorting_with_references() {
let values = vec!["foo", "qux", "bar"];
let mut array = toml_edit::Array::from_iter(values);
array.sort_by(|lhs, rhs| lhs.as_str().cmp(&rhs.as_str()));
}

0 comments on commit ddadd45

Please sign in to comment.