1#![forbid(unsafe_code)]
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum HardnessScale {
21 Brinell,
22 Vickers,
23 RockwellA,
24 RockwellB,
25 RockwellC,
26 Mohs,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq)]
30pub struct Hardness {
31 value: f64,
32 scale: HardnessScale,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum HardnessError {
37 InvalidValue,
38 ScaleMismatch,
39}
40
41impl Hardness {
42 pub fn new(value: f64, scale: HardnessScale) -> Result<Self, HardnessError> {
43 if !value.is_finite() || value <= 0.0 {
44 return Err(HardnessError::InvalidValue);
45 }
46
47 Ok(Self { value, scale })
48 }
49
50 #[must_use]
51 pub fn value(&self) -> f64 {
52 self.value
53 }
54
55 #[must_use]
56 pub fn scale(&self) -> HardnessScale {
57 self.scale
58 }
59}
60
61#[must_use]
62pub fn same_scale(a: Hardness, b: Hardness) -> bool {
63 a.scale == b.scale
64}
65
66pub fn is_harder_than(a: Hardness, b: Hardness) -> Result<bool, HardnessError> {
67 if !same_scale(a, b) {
68 return Err(HardnessError::ScaleMismatch);
69 }
70
71 Ok(a.value > b.value)
72}
73
74#[cfg(test)]
75mod tests {
76 use super::{Hardness, HardnessError, HardnessScale, is_harder_than, same_scale};
77
78 #[test]
79 fn compares_hardness_values_on_the_same_scale() {
80 let first = Hardness::new(200.0, HardnessScale::Vickers).unwrap();
81 let second = Hardness::new(180.0, HardnessScale::Vickers).unwrap();
82
83 assert!(same_scale(first, second));
84 assert!(is_harder_than(first, second).unwrap());
85 assert!(!is_harder_than(second, first).unwrap());
86 }
87
88 #[test]
89 fn rejects_cross_scale_comparisons() {
90 let first = Hardness::new(60.0, HardnessScale::RockwellC).unwrap();
91 let second = Hardness::new(8.0, HardnessScale::Mohs).unwrap();
92
93 assert!(!same_scale(first, second));
94 assert_eq!(
95 is_harder_than(first, second),
96 Err(HardnessError::ScaleMismatch)
97 );
98 }
99
100 #[test]
101 fn rejects_invalid_hardness_values() {
102 assert_eq!(
103 Hardness::new(0.0, HardnessScale::Brinell),
104 Err(HardnessError::InvalidValue)
105 );
106 assert_eq!(
107 Hardness::new(f64::NAN, HardnessScale::Mohs),
108 Err(HardnessError::InvalidValue)
109 );
110 }
111}