pub(crate) fn sort_total_by_key_at<T, K, F>(site: &'static str, v: &mut [T], mut f: F)
where
K: Ord + std::fmt::Debug,
F: FnMut(&T) -> K,
{
v.sort_unstable_by_key(&mut f);
#[cfg(any(debug_assertions, feature = "strict-order"))]
{
for w in v.windows(2) {
let (a, b) = (f(&w[0]), f(&w[1]));
assert!(
a != b,
"{site}: sort key is NOT a total order — two elements produced {a:?}. \
`sort_unstable` then resolves them by input order, which for an ECS query is not \
stable across `App` instances. Widen the key, or use a canonical whole-value sort."
);
}
}
#[cfg(not(any(debug_assertions, feature = "strict-order")))]
let _ = site;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_total_key_sorts_and_does_not_trip_the_check() {
let mut v = vec![3u32, 1, 2];
sort_total_by_key_at("order::tests", &mut v, |x| *x);
assert_eq!(v, vec![1, 2, 3]);
}
#[test]
#[cfg(any(debug_assertions, feature = "strict-order"))]
#[should_panic(expected = "sort key is NOT a total order")]
fn a_duplicated_key_panics_naming_the_site() {
let mut v = vec![(1u32, 'a'), (1u32, 'b')];
sort_total_by_key_at("order::tests::duplicated", &mut v, |x| x.0);
}
}