Rust: Advanced Rust Pattern Matching
Last updated: 2026-08-26
Pattern matching is one of Rust’s most powerful language features, and advanced techniques such as
matchguards,@bindings, and multiple patterns allow you to exercise more fine-grained control over your matches—not just “matching values,” but “matching conditions.”
If basic pattern matching is like a multiple-choice question (choosing one branch to execute), then advanced pattern matching is like a composite question—you can check values, bind references, and evaluate additional conditions all at the same time.
1. What You'll Learn
- Use the
ifmatch guard to add additional conditions to a match branch - Use
@to bind values simultaneously when a match is found - Use
|to combine multiple patterns (multi-pattern matching) - Use
..and..=for range matching - Use the
matches!macro for concise Boolean matching checks - Deconstructing the Nested Pattern of Structures and Enumerations
2. A Story About an Employee Performance Rating
(1) The Struggle: Using an if-else chain for a comprehensive rating
Tom is the company's HR manager, and he needs to assign comprehensive ratings based on employees' performance scores and attendance records.
The rules are as follows:
| Level | Performance Score | Attendance Requirements |
|---|---|---|
| A+ | ≥95 | Perfect attendance (≥22 days) |
| A | ≥85 | Attendance ≥ 20 days |
| B | ≥70 | Attendance ≥ 18 days |
| C | ≥60 | — |
| D | <60 | — |
At first, he wrote a long string of if-else:
fn rate_employee(score: u32, attendance: u32) -> &'static str {
if score >= 95 && attendance >= 22 {
"A+"
} else if score >= 85 && attendance >= 20 {
"A"
} else if score >= 70 && attendance >= 18 {
"B"
} else if score >= 60 {
"C"
} else {
"D"
}
}
Although this code runs, it has several issues: the conditions are scattered throughout a chain of if-else statements, making it hard to read, and there is no exhaustive check—if rating rules are added in the future, it would be easy to overlook them. Furthermore, the coupling between scores and attendance is not clear enough.
(2) Advanced Approaches to Pattern Matching in Rust
fn rate_employee(score: u32, attendance: u32) -> &'static str {
match score {
// Guard Requirements: Meeting the Score Requirement + Attendance Requirements Met
s if s >= 95 && attendance >= 22 => "A+",
s if s >= 85 && attendance >= 20 => "A",
s if s >= 70 && attendance >= 18 => "B",
s if s >= 60 => "C",
_ => "D", // Fallback: score < 60
}
}
fn main() {
let employees = [
("Alice", 98, 23),
("Bob", 88, 21),
("Charlie", 88, 17), // High scores but insufficient attendance
("Diana", 72, 19),
("Eve", 55, 20),
];
for (name, score, attendance) in &employees {
let rating = rate_employee(*score, *attendance);
println!("{:8} | Score: {:2} | Attendance: {:2} days | Rating: {}",
name, score, attendance, rating);
}
}
Output:
Alice | Score: 98 | Attendance: 23 days | Rating: A+
Bob | Score: 88 | Attendance: 21 days | Rating: A
Charlie | Score: 88 | Attendance: 17 days | Rating: B
Diana | Score: 72 | Attendance: 19 days | Rating: B
Eve | Score: 55 | Attendance: 20 days | Rating: D
matchThe guard makes the conditions for each branch immediately clear: the "AND" relationship between score and attendance is clearly visible._The catch-all branch ensures exhaustiveness. Furthermore, the semantics ofs if s >= ...for different score ranges are more intuitive than those ofelse if.
3. Overview of Advanced Pattern Matching
(1) Concept Map
graph TB
A[Advanced Pattern Matching] --> B[match Guard]
A --> C[@ Bind]
A --> D[Multimode |]
A --> E[Range Matching]
A --> F[matches! Macro]
A --> G[Deconstruction Patterns]
B --> B1["match x { n if n > 10 => ... }"]
C --> C1["match x { e @ 1..=5 => ... }"]
D --> D1["match x { 1 | 3 | 5 => ... }"]
E --> E1["match x { 1..=10 => ... }"]
F --> F1["if matches!(x, 1..=5) { ... }"]
G --> G1["let Point { x, y } = p;"]
G --> G2["match opt { Some(v @ 1..=10) => ... }"]
(2) Comparison of Matching Methods
| Method | Syntax | When to Use | Example |
|---|---|---|---|
| Basic match | match x { PAT => .. } |
Simple value match | match x { 1 => "one" } |
| match guard | match x { PAT if COND => .. } |
Match + additional conditions | n if n > 10 && n % 2 == 0 |
| @ Binding | e @ PAT => .. |
Binding value when matched | e @ 1..=10 => e |
| Multi-mode | | PAT1 | PAT2 => .. |
Multiple modes share the same branch | 1 | 3 | 5 => "odd" |
| Range ..= | PAT1..=PAT2 => .. |
Matches a range of values | 1..=5 => "small" |
| matches! macro | matches!(x, PAT) |
Boolean result only | if matches!(x, 1..=5) |
| Deconstruction | let PAT = value |
Decomposing Composite Types | let (a, b) = pair |
(3) Quick Reference for Pattern Types
| Pattern Type | Syntax | Match Target | Example |
|---|---|---|---|
| Literal | 1 / "hello" |
Exact Value | match x { 1 => ... } |
| Variable Binding | x |
Any value, bound to x | match x { n => ... } |
| Wildcard | _ |
Any value, ignored | match x { _ => ... } |
| Multi-mode | 1 | 2 | 3 |
Multiple values | match x { 1 | 2 => ... } |
| Range | 1..=5 |
Closed interval range | match x { 1..=5 => ... } |
| Deconstructing Tuples | (a, b) |
Tuples | match pair { (x, y) => ... } |
| Deconstructing Structures | Point { x, y } |
Structures | match p { Point { x, y } => ... } |
| Deconstructing Enumerations | Some(v) |
Enumeration Variants | match opt { Some(v) => ... } |
| @ Binding | e @ 1..=10 |
Range + Binding | match x { e @ 1..=10 => ... } |
| Guard | x if x > 0 |
Mode + Conditions | match x { n if n > 0 => ... } |
| Ignore the rest | .. |
Ignore some fields | match p { Point { x, .. } => ... } |
4. Advanced Matching Examples
▶ Example 1: Match Guard + @ Binding + Multi-Mode (Difficulty ⭐⭐)
Output:
[@ binding] score <s> captured for A+ rating
[@ binding] score <s> captured for A rating
[@ binding] score <s> captured for B rating
[guard] score <s> is below 60, rating D
[wildcard] unexpected combination
<emp.name>:
Rating: <rating>, Bonus: <bonus>%, Special: <special>
// ============================================
// Comprehensive Example: Employee Performance Rating System
// Display match Guard, @ Bind, Multi-pattern
// ============================================
#[derive(Debug)]
enum Department {
Engineering,
Sales,
HR,
Management,
}
#[derive(Debug)]
struct Employee {
name: String,
score: u32,
attendance: u32,
department: Department,
}
impl Employee {
/// Rate employee using advanced pattern matching.
/// Returns (rating, bonus_percentage).
fn rate(&self) -> (&'static str, u32) {
match (self.score, self.attendance) {
// @ binding: capture the matched score value
s @ 95..=100 if self.attendance >= 22 => {
println!(" [@ binding] score {} captured for A+ rating", s);
("A+", 30)
}
s @ 85..=94 if self.attendance >= 20 => {
println!(" [@ binding] score {} captured for A rating", s);
("A", 20)
}
s @ 70..=84 if self.attendance >= 18 => {
println!(" [@ binding] score {} captured for B rating", s);
("B", 10)
}
// Multi-pattern: 60..=69 OR exactly 70 with low attendance
60..=69 | 70..=84 => {
("C", 5) // No @ binding needed here
}
// match guard with combined conditions
s if s < 60 => {
println!(" [guard] score {} is below 60, rating D", s);
("D", 0)
}
// Catch-all: should not reach normally
_ => {
println!(" [wildcard] unexpected combination");
("Unknown", 0)
}
}
}
/// Check if this employee qualifies for special bonus
/// using matches! macro.
fn has_special_bonus(&self) -> bool {
// matches! returns true if the pattern matches
matches!(self.department, Department::Engineering | Department::Management)
&& self.score >= 90
}
}
fn main() {
let employees = vec![
Employee {
name: String::from("Alice"),
score: 97,
attendance: 23,
department: Department::Engineering,
},
Employee {
name: String::from("Bob"),
score: 88,
attendance: 21,
department: Department::Sales,
},
Employee {
name: String::from("Charlie"),
score: 88,
attendance: 17,
department: Department::HR,
},
Employee {
name: String::from("Diana"),
score: 65,
attendance: 20,
department: Department::HR,
},
Employee {
name: String::from("Eve"),
score: 42,
attendance: 15,
department: Department::Management,
},
];
for emp in &employees {
println!("{}:", emp.name);
let (rating, bonus) = emp.rate();
let special = emp.has_special_bonus();
println!(" Rating: {}, Bonus: {}%, Special: {}",
rating, bonus, special);
println!();
}
}
Output:
Alice:
[@ binding] score 97 captured for A+ rating
Rating: A+, Bonus: 30%, Special: true
Bob:
[@ binding] score 88 captured for A rating
Rating: A, Bonus: 20%, Special: false
Charlie:
[@ binding] score 88 captured for B rating
Rating: B, Bonus: 10%, Special: false
Diana:
Rating: C, Bonus: 5%, Special: false
Eve:
[guard] score 42 is below 60, rating D
Rating: D, Bonus: 0%, Special: true
This example comprehensively demonstrates three advanced matching techniques:
@binds captured values for later use;ifuses guards to add additional conditions (such as attendance requirements);|uses multimode to allow different ranges to share the same branch; andmatches!uses a macro to concisely determine "whether it belongs to one of several variants."
▶ Example 2: Deconstructing Nested Structures and Enums (Difficulty ⭐⭐⭐)
Output:
[range] High priority task (level <task.priority>)
[nested destructure] Task #<id> '<title>' completed by <reviewer> at <finished_at> (priority <priority>)
[@ binding] Task '<task.title>' blocked by <blocked_by>: <reason>
[guard] Important in-progress task (priority <priority>)
[wildcard] Task '<task.status>': status <task.title>
Task #<task.id>: <task.title>
// ============================================
// Nested Deconstruction: Matching Enums in Structures, Tuples in Enumerations
// ============================================
#[derive(Debug)]
enum TaskStatus {
Pending,
InProgress,
Completed { finished_at: String, reviewer: String },
Blocked { reason: String, blocked_by: String },
}
#[derive(Debug)]
struct Task {
id: u32,
title: String,
status: TaskStatus,
priority: u8, // 1 (highest) to 5 (lowest)
}
fn analyze_task(task: &Task) {
// Destructure the Task struct directly in match
match task {
// Multi-pattern: priority 1 or 2 with any status
Task { priority: 1..=2, .. } => {
println!(" [range] High priority task (level {})", task.priority);
}
// Destructure both Task and TaskStatus::Completed
Task {
id,
title,
status:
TaskStatus::Completed {
finished_at,
reviewer,
},
priority,
} => {
println!(" [nested destructure] Task #{} '{}' completed by {} at {} (priority {})",
id, title, reviewer, finished_at, priority);
}
// Destructure TaskStatus::Blocked with @ binding on reason
Task {
status:
TaskStatus::Blocked {
reason,
blocked_by,
},
..
} => {
println!(" [@ binding] Task '{}' blocked by {}: {}",
task.title, blocked_by, reason);
}
// Match guard on enum variant
Task {
status: TaskStatus::InProgress,
priority,
..
} if *priority <= 3 => {
println!(" [guard] Important in-progress task (priority {})", priority);
}
// Wildcard for remaining
_ => {
println!(" [wildcard] Task '{}': status {:?}", task.title, task.status);
}
}
}
fn main() {
let tasks = vec![
Task {
id: 1,
title: String::from("Security audit"),
status: TaskStatus::Completed {
finished_at: String::from("2026-07-01"),
reviewer: String::from("Alice"),
},
priority: 1,
},
Task {
id: 2,
title: String::from("Update dependencies"),
status: TaskStatus::Blocked {
reason: String::from("Waiting for approval"),
blocked_by: String::from("Manager"),
},
priority: 2,
},
Task {
id: 3,
title: String::from("Write documentation"),
status: TaskStatus::InProgress,
priority: 3,
},
Task {
id: 4,
title: String::from("Fix typo in README"),
status: TaskStatus::Pending,
priority: 5,
},
];
for task in &tasks {
println!("Task #{}: {}", task.id, task.title);
analyze_task(task);
println!();
}
}
Output:
Task #1: Security audit
[nested destructure] Task #1 'Security audit' completed by Alice at 2026-07-01 (priority 1)
Task #2: Update dependencies
[range] High priority task (level 2)
Task #3: Write documentation
[guard] Important in-progress task (priority 3)
Task #4: Fix typo in README
[wildcard] Task 'Fix typo in README': status Pending
Nested destructuring is a powerful feature of Rust’s pattern matching: you can destruct structs, enums, and tuples simultaneously within a single
matchbranch...ignores fields you’re not interested in, and@binds and captures inner values. Note thatTask { priority: 1..=2, .. }matches tasks with any priority of 1 or 2—because althoughBlockedcomes later in the pattern,rangematches tasks with priority=2 first.
▶ Example 3: Combining the matches! macro with if let (Difficulty: ⭐⭐)
Output:
<status>:
is_success: <is_success(status)>
is_server_error: <is_server_error(status)>
is_redirect_to_301: <is_redirect_to(status, 301)>
category: <categorize(status)>
>> Server error code: <code>
// ============================================
// matches! Macro: Simple Boolean Pattern Matching
// ============================================
#[derive(Debug, PartialEq)]
enum HttpStatus {
Ok,
NotFound,
ServerError(u16),
Redirect(u16),
}
/// Check if a status is a success (2xx).
fn is_success(status: &HttpStatus) -> bool {
matches!(status, HttpStatus::Ok)
}
/// Check if a status is a server error (5xx).
fn is_server_error(status: &HttpStatus) -> bool {
matches!(status, HttpStatus::ServerError(_))
}
/// Check if a status is a redirect (3xx) with specific code.
fn is_redirect_to(status: &HttpStatus, code: u16) -> bool {
matches!(status, HttpStatus::Redirect(c) if *c == code)
}
/// Get status category using multiple matches! checks.
fn categorize(status: &HttpStatus) -> &'static str {
if matches!(status, HttpStatus::Ok) {
"Success"
} else if matches!(status, HttpStatus::Redirect(301 | 302)) {
"Temporary Redirect"
} else if matches!(status, HttpStatus::Redirect(_)) {
"Other Redirect"
} else if matches!(status, HttpStatus::NotFound) {
"Not Found (404)"
} else if matches!(status, HttpStatus::ServerError(500..=599)) {
"Server Error"
} else {
"Unknown"
}
}
fn main() {
let statuses = vec![
HttpStatus::Ok,
HttpStatus::NotFound,
HttpStatus::Redirect(301),
HttpStatus::Redirect(307),
HttpStatus::ServerError(500),
HttpStatus::ServerError(503),
];
for status in &statuses {
println!("{:?}:", status);
println!(" is_success: {}", is_success(status));
println!(" is_server_error: {}", is_server_error(status));
println!(" is_redirect_to_301: {}", is_redirect_to(status, 301));
println!(" category: {}", categorize(status));
// if let with matches!-style pattern
if let HttpStatus::ServerError(code) = status {
println!(" >> Server error code: {}", code);
}
println!();
}
}
Output:
Ok:
is_success: true
is_server_error: false
is_redirect_to_301: false
category: Success
NotFound:
is_success: false
is_server_error: false
is_redirect_to_301: false
category: Not Found (404)
Redirect(301):
is_success: false
is_server_error: false
is_redirect_to_301: true
category: Temporary Redirect
Redirect(307):
is_success: false
is_server_error: false
is_redirect_to_301: false
category: Other Redirect
ServerError(500):
is_success: false
is_server_error: true
is_redirect_to_301: false
category: Server Error
ServerError(503):
is_success: false
is_server_error: true
is_redirect_to_301: false
category: Server Error
The
matches!macro returns abool, which is suitable for pattern matching inifconditions. It supports all pattern syntax, includingifguards, multiple patterns, and range matching. Unlikeif let,matches!does not bind variables; it only returnstrue/false—it is the most concise option when you only need to evaluate a condition without retrieving a value.
▶ Example 4: Comprehensive Exercise—Expression Evaluator (Difficulty ⭐⭐⭐)
Output:
Expression<s>: <val> = <i + 1>
Expression<i + 1>: <s> = Error (Division by Zero)
// ============================================
// Comprehensive Example: Implementing Expression Evaluation Using Nested Pattern Matching
// ============================================
#[derive(Debug, Clone)]
enum Expr {
Number(f64),
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Neg(Box<Expr>),
}
fn eval(expr: &Expr) -> Option<f64> {
match expr {
Expr::Number(n) => Some(*n),
Expr::Add(a, b) => Some(eval(a)? + eval(b)?),
Expr::Sub(a, b) => Some(eval(a)? - eval(b)?),
Expr::Mul(a, b) => Some(eval(a)? * eval(b)?),
Expr::Div(a, b) => {
let divisor = eval(b)?;
if divisor == 0.0 { None } else { Some(eval(a)? / divisor) }
}
Expr::Neg(a) => Some(-eval(a)?),
}
}
fn expr_to_string(expr: &Expr) -> String {
match expr {
Expr::Number(n) => format!("{:.0}", n),
Expr::Add(a, b) => format!("({} + {})", expr_to_string(a), expr_to_string(b)),
Expr::Sub(a, b) => format!("({} - {})", expr_to_string(a), expr_to_string(b)),
Expr::Mul(a, b) => format!("({} * {})", expr_to_string(a), expr_to_string(b)),
Expr::Div(a, b) => format!("({} / {})", expr_to_string(a), expr_to_string(b)),
Expr::Neg(a) => format!("-{}", expr_to_string(a)),
}
}
fn main() {
let expr1 = Expr::Add(
Box::new(Expr::Number(10.0)),
Box::new(Expr::Mul(Box::new(Expr::Number(3.0)), Box::new(Expr::Number(4.0)))),
);
let expr2 = Expr::Div(
Box::new(Expr::Sub(Box::new(Expr::Number(20.0)), Box::new(Expr::Number(5.0)))),
Box::new(Expr::Number(3.0)),
);
let expr3 = Expr::Neg(Box::new(Expr::Number(42.0)));
let expr4 = Expr::Div(Box::new(Expr::Number(10.0)), Box::new(Expr::Number(0.0)));
let exprs = [expr1, expr2, expr3, expr4];
for (i, expr) in exprs.iter().enumerate() {
let s = expr_to_string(expr);
match eval(expr) {
Some(val) => println!("Expression{}: {} = {:.2}", i + 1, s, val),
None => println!("Expression{}: {} = Error (Division by Zero)", i + 1, s),
}
}
}
Output:
Expression1: (10 + (3 * 4)) = 22.00
Expression2: ((20 - 5) / 3) = 5.00
Expression3: -42 = -42.00
Expression4: (10 / 0) = Error (Division by Zero)
Recursive enumeration combined with nested destructuring is one of the most powerful applications of pattern matching.
Box<Expr>Allows enumerations to reference themselves (sinceBoxis a fixed-size pointer).evalUses the?operator to elegantly propagate non-zero errors.
▶ Example 5: Pattern Matching and JSON-like Data Structures (Difficulty ⭐⭐⭐)
Output:
Type: <type_name(&data)>
Number of nodes: <deep_count(&data)>
Name: <name>
Average Score: <avg>
City: <city>
// ============================================
// Processing Dynamically Typed Data Using Pattern Matching
// ============================================
#[derive(Debug, Clone)]
enum Value {
Null,
Bool(bool),
Number(f64),
String(String),
Array(Vec<Value>),
Object(Vec<(String, Value)>),
}
fn type_name(val: &Value) -> &str {
match val {
Value::Null => "null",
Value::Bool(_) => "bool",
Value::Number(_) => "number",
Value::String(_) => "string",
Value::Array(_) => "array",
Value::Object(_) => "object",
}
}
fn deep_count(val: &Value) -> usize {
match val {
Value::Array(items) => items.iter().map(deep_count).sum::<usize>() + 1,
Value::Object(entries) => entries.iter().map(|(_, v)| deep_count(v)).sum::<usize>() + 1,
_ => 1,
}
}
fn find_key<'a>(val: &'a Value, key: &str) -> Option<&'a Value> {
match val {
Value::Object(entries) => entries.iter().find(|(k, _)| k == key).map(|(_, v)| v),
_ => None,
}
}
fn main() {
let data = Value::Object(vec![
("name".into(), Value::String("Alice".into())),
("age".into(), Value::Number(30.0)),
("active".into(), Value::Bool(true)),
("scores".into(), Value::Array(vec![
Value::Number(95.0),
Value::Number(88.0),
Value::Number(92.0),
])),
("address".into(), Value::Object(vec![
("city".into(), Value::String("Beijing".into())),
("zip".into(), Value::Number(100000.0)),
])),
]);
println!("Type: {}", type_name(&data));
println!("Number of nodes: {}", deep_count(&data));
if let Some(Value::String(name)) = find_key(&data, "name") {
println!("Name: {}", name);
}
if let Some(Value::Array(scores)) = find_key(&data, "scores") {
let avg: f64 = scores.iter()
.filter_map(|v| if let Value::Number(n) = v { Some(*n) } else { None })
.sum::<f64>() / scores.len() as f64;
println!("Average Score: {:.1}", avg);
}
if let Some(Value::Object(addr)) = find_key(&data, "address") {
if let Some(Value::String(city)) = find_key(&Value::Object(addr.clone()), "city") {
println!("City: {}", city);
}
}
}
Output:
Type: object
Number of nodes: 11
Name: Alice
Average Score: 91.7
City: Beijing
Use enumerations to simulate dynamically typed data (such as JSON), and safely extract and iterate through it using pattern matching.
find_keyUseif letfor secure access, andfilter_mapcombined with pattern matching to filter and transform values in an array.
❓ FAQ
match guard (if guard) and a match branch determined?match guard is a condition within a branch—the pattern is matched first, then the guard is evaluated. If the guard returns false, the program proceeds to the next branch (it does not fall-through to the next one!). Variables bound by the pattern match can be used in the guard condition.e @ 1..=10 means "if the value is between 1 and 10, bind that value to e." Writing x directly matches any value and binds it to x. @ allows you to restrict the range while still using that value... matches any number of elements (and ignores them), while _ matches a single position. When destructuring a struct, Struct { a, .. } ignores all other fields; in a tuple, (x, .., z) matches the first and last elements. _ ignores only one position. .. can only be used once in the same pattern.matches! macro and if let?matches! returns a bool (without binding a variable), while if let binds a variable and executes the code block. If you only need to check “whether it matches” without needing the matched value, use matches!. If you need to destruct the value and use it, use if let or match.Some(1) | Some(2) is acceptable, but Some(1) | None is not, because Some has data elements while None does not.PartialOrd (i8-u128, u8-u128) and char are supported. For example, match c { 'a'..='z' => "lowercase", 'A'..='Z' => "uppercase", _ => "other" }. Range matching for f64 is not supported.📖 Summary
- match guard (if guard) Adds a conditional check after pattern matching to enable fine-grained control through "pattern + condition"
- @ Binding Captures values when matching specific patterns to avoid duplicate calculations or re-matching
- | Multi-mode Allows multiple modes to share the same code branch, reducing duplication
- .. and ..= Range matching can match integer ranges and character ranges;
..ignores the remaining fields during decomposition - matches! macro Returns a Boolean value; ideal for concise pattern-matching checks in if statements
- Nested Destructuring allows you to destruct multiple levels of composite types—such as structs, enumerations, and tuples—simultaneously within a
matchstatement.
📝 Exercises
-
Difficulty ⭐: Write a function
fn describe_number(n: i32) -> &'static strthat usesmatchand range matching:1..=10returns "small,"11..=100returns "medium,"101..=1000returns "large," and all others return "out of range." Test with 5, 50, 500, and 5000 in themainfunction. -
Difficulty ⭐⭐: Define an enumeration
Temperaturethat includes two variants:Celsius(f64)andFahrenheit(f64). Write a functionfn describe_temp(temp: &Temperature) -> &'static strthat uses thematches!macro and theifguard to determine: if Celsius is greater than 30 or Fahrenheit is greater than 86, return "hot"; if Celsius is less than 0 or Fahrenheit is less than 32, return "cold"; otherwise, return "moderate". Test the four temperatures in themainfunction. -
Difficulty ⭐⭐⭐: Define a struct
Orderthat containsid: u32,items: Vec<String>,total: f64, andstatus: OrderStatus(enumeration:Pending,Shipped { tracking: String },Delivered { date: String }). Implement a methodfn summary(&self) -> Stringthat uses nested destructuring andmatchguards to return different summary messages based on the status and total amount (e.g., for shipped orders where the total amount is greater than 1,000, display "High-value order shipped, tracking: xxx"). In themainfunction, create three orders and print their summaries.