Advanced Pattern Matching in Rust
Rust's match expression is a powerful tool for control flow, enabling sophisticated pattern matching that goes beyond simple equality checks. This challenge will test your ability to leverage match with various pattern types, including destructuring, guards, and the use of the _ wildcard. Mastering these techniques is crucial for writing idiomatic and robust Rust code.
Problem Description
You are tasked with creating a function that processes a complex data structure representing different types of geometric shapes and their properties. The function should use Rust's match expression to perform specific actions based on the type and attributes of the shape.
Requirements:
-
Define an Enum: Create an enum called
Shapethat can represent:Pointwithxandyinteger coordinates.Circlewith acenter(which is aPoint) and aradius(a float).Rectanglewith atop_left(aPoint) andwidthandheight(both floats).Trianglewith threePointvertices.
-
Implement a
process_shapeFunction: Create a public functionprocess_shapethat takes aShapeenum variant as input and returns aStringdescribing the shape and its properties. -
Use
matchfor Pattern Matching: Withinprocess_shape, use amatchexpression to handle eachShapevariant. -
Destructuring: For
Point,Circle, andRectangle, destructure the constituent parts (coordinates, center, radius, dimensions) to access their values within thematcharms. -
Wildcard (
_): When processing aTriangle, you don't need to inspect the individual coordinates of its vertices. Use the_wildcard to ignore them. -
Pattern Guards (Optional but encouraged): For
CircleandRectangle, add a pattern guard to check for specific conditions:- If a
Circlehas a radius less than or equal to 0, treat it as an invalid circle. - If a
Rectanglehas a width or height less than or equal to 0, treat it as an invalid rectangle. - For valid circles and rectangles, include their dimensions in the output string.
- If a
-
Output Formatting: The output string should be descriptive and clearly indicate the type of shape and its relevant properties.
Expected Behavior:
The process_shape function should correctly identify each Shape variant and format its output string based on the matched pattern and any applied guards.
Edge Cases:
- Invalid
Circle(radius <= 0). - Invalid
Rectangle(width <= 0 or height <= 0). - Handling of
PointandTrianglewithout specific numeric guards.
Examples
Example 1:
Input: Shape::Point { x: 10, y: 20 }
Output: "This is a Point at (10, 20)."
Explanation: The `Point` variant is matched, and its `x` and `y` coordinates are extracted and used in the output string.
Example 2:
Input: Shape::Circle { center: Shape::Point { x: 5, y: 5 }, radius: 7.5 }
Output: "This is a Circle centered at (5, 5) with radius 7.5."
Explanation: The `Circle` variant is matched. The nested `Point` is destructured, and the `radius` is used in the output.
Example 3:
Input: Shape::Rectangle { top_left: Shape::Point { x: 0, y: 10 }, width: 5.0, height: 8.0 }
Output: "This is a Rectangle with top-left corner at (0, 10), width 5.0, and height 8.0."
Explanation: The `Rectangle` variant is matched, destructuring its properties and including them in the output.
Example 4:
Input: Shape::Triangle { p1: Shape::Point { x: 1, y: 2 }, p2: Shape::Point { x: 3, y: 4 }, p3: Shape::Point { x: 5, y: 6 } }
Output: "This is a Triangle."
Explanation: The `Triangle` variant is matched. The `_` wildcard is used to ignore the individual point data.
Example 5 (with guards):
Input: Shape::Circle { center: Shape::Point { x: 0, y: 0 }, radius: -2.0 }
Output: "Invalid Circle: radius cannot be negative."
Explanation: The `Circle` pattern is matched, but the guard `radius <= 0.0` is true, so the alternative output is produced.
Example 6 (with guards):
Input: Shape::Rectangle { top_left: Shape::Point { x: 1, y: 1 }, width: 0.0, height: 10.0 }
Output: "Invalid Rectangle: width and height must be positive."
Explanation: The `Rectangle` pattern is matched, but the guard `width <= 0.0` is true, triggering the invalid rectangle message.
Constraints
- Integer coordinates for
Pointwill be within the range ofi32. - Float values for
radius,width, andheightwill be standardf64. - The
process_shapefunction must be efficient, with its time complexity for any given shape being constant, O(1), due to direct pattern matching.
Notes
- Consider how to define the
Pointstruct or enum within your solution. It can be an inner enum variant or a separate struct used within theShapeenum. For this challenge, let's definePointas a separate struct. - The use of pattern guards is an excellent way to add conditional logic directly within
matcharms, making your code cleaner. - Think about how to handle the nested
Pointstructure withinCircleandRectangle.