We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Shape Your Data: Structs, Enums, Pattern Matching step 20 of 26
Derive consistent ordering for versions and priorities
Fix the starter's inconsistent comparison traits so both sorting functions
follow the rules below. Use derived PartialEq, Eq, PartialOrd and Ord
for the supplied types, without a custom comparison function.
pub fn sort_versions(versions: Vec<String>) -> Vec<String>
pub fn rank_priorities(items: Vec<(String, String)>) -> Vec<String>
Sort version strings by three numeric components
Split each string on . and use only the first three parts as major, minor
and patch. Parse each part as u32; a missing or invalid part becomes zero.
Ignore additional parts. Do not trim whitespace.
Rust's integer parser accepts decimal digits with an optional leading +
and leading zeros, provided the number fits in u32. Empty parts, negative
values, whitespace, underscores and values above 4294967295 fail to parse.
Compare (major, minor, patch) numerically in that order. When these three
values tie, compare the original strings using Rust's lexicographic String
order. Return the original strings, preserving all duplicates.
Examples:
["1.10.0", "1.9.0"]becomes["1.9.0", "1.10.0"].["2.0", "2.0.0", "2"]becomes["2", "2.0", "2.0.0"]."1..3.extra"parses as(1, 0, 3)."1.2.3-beta"parses as(1, 2, 0).
This is a simplified exercise parser, not a SemVer implementation. It does not interpret prerelease identifiers or build metadata.
Rank priorities, then names
Each pair is (name, priority_label). Match labels exactly: critical comes
first, followed by high, then normal. Every other label means low priority,
including low, High, and strings with extra whitespace.
Return the names sorted by that priority and then by name. Names and version strings may contain arbitrary Unicode. String comparison is lexicographic, not locale-aware or case-insensitive. Names are preserved unchanged, and duplicate items still produce duplicate names. Each function returns an empty vector for empty input; the harness tests both functions in each case.
Struct fields are compared in declaration order
A derived struct comparison checks the first field, then the next only if the preceding fields tie. This complete example sorts a two-part version:
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Release {
major: u32,
minor: u32,
}
fn main() {
let mut releases = [
Release { major: 1, minor: 10 },
Release { major: 2, minor: 0 },
Release { major: 1, minor: 9 },
];
releases.sort();
assert_eq!(releases, [
Release { major: 1, minor: 9 },
Release { major: 1, minor: 10 },
Release { major: 2, minor: 0 },
]);
}
The supplied Version adds a third field, patch. A tuple such as
(Version, String) already implements lexicographic ordering when its
elements do, so the second element supplies the original-string tie-break.
No handwritten comparator is needed.
Enum order depends on discriminants
The supplied Priority variants are Critical, High, Normal, Low,
with no explicit discriminant values. Their derived order follows that
declaration order. Sorting (Priority, String) ascending therefore ranks
urgency first and names second.
More generally, derived enum ordering compares discriminants before payload fields. Explicit discriminant values can change the order: a variant declared first with value 2 sorts after one declared second with value 1. Within the same variant, payload fields are compared lexicographically.
Field order and enum discriminants are therefore part of the comparison behavior. Keep a test that expresses the intended order when reorganizing declarations. See the Ord documentation.
Keep PartialOrd and Ord consistent
The starter derives Ord for all Version fields but implements PartialOrd
using only major. For 1.9.0 and 1.10.0, those implementations disagree:
cmp returns Less, while partial_cmp returns Some(Equal).
An Ord type must satisfy a.partial_cmp(b) == Some(a.cmp(b)), along with the
ordering and equality laws. Clippy's derive_ord_xor_partial_ord flags the
mixed implementations. Remove the manual implementation and derive all four
comparison traits together. Merely silencing the lint leaves the inconsistency.
Handwritten implementations are not inherently inconsistent; they must agree
on the same order. For an Ord type, delegating partial_cmp to
Some(self.cmp(other)) is the canonical approach. This exercise uses derives
because declaration order already expresses the desired comparisons.
A sort may panic when its comparison rules are inconsistent, but it is not a validator for those rules. Successful completion does not prove correctness, and invalid ordering can leave the result unspecified. Test comparisons and expected outputs directly rather than depending on a panic. Whether a panic unwinds or aborts depends on the build's panic strategy.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.