use std::f64::consts::PI;
use std::fmt;
/// Custom error type for circle calculation failures.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CircleError {
NegativeRadius,
}
impl fmt::Display for CircleError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CircleError::NegativeRadius => write!(f, "Radius cannot be negative or NaN."),
}
}
}
// Implement standard Error trait for interoperability
impl std::error::Error for CircleError {}
/// Structure to hold the calculated geometric metrics of a circle cleanly.
#[derive(Debug, Clone, Copy)]
pub struct CircleMetrics {
pub diameter: f64,
pub circumference: f64,
pub area: f64,
}
/// Calculates the diameter, circumference, and area of a circle.
///
/// # Arguments
/// * `radius` - The radius of the circle (must be a non-negative number).
///
/// # Returns
/// * `Result<CircleMetrics, CircleError>` - The calculated metrics on success, or an error if invalid.
pub fn calculate_circle_metrics(radius: f64) -> Result<CircleMetrics, CircleError> {
// Guard clause: radius cannot be negative or NaN
if radius < 0.0 || radius.is_nan() {
return Err(CircleError::NegativeRadius);
}
let diameter = 2.0 * radius;
let circumference = 2.0 * PI * radius;
// Standard multiplication (radius * radius) is more efficient than powi() or powf()
let area = PI * (radius * radius);
Ok(CircleMetrics {
diameter,
circumference,
area,
})
}
fn main() {
let radius = 3.0;
// Handle the Result using pattern matching
match calculate_circle_metrics(radius) {
Ok(metrics) => {
println!("Radius: {:.2}", radius);
println!("Diameter: {:.2}", metrics.diameter);
println!("Circumference: {:.2}", metrics.circumference);
println!("Area: {:.2}", metrics.area);
}
Err(e) => {
eprintln!("Error: {}", e);
std::process::exit(1);
}
}
}
/*
run:
Radius: 3.00
Diameter: 6.00
Circumference: 18.85
Area: 28.27
*/