unitx_core/
validation.rs

1use crate::error::UnitxError;
2
3pub fn validate_temperature_value(value: f64) -> Result<(), UnitxError> {
4    if !value.is_finite() {
5        return Err(UnitxError::ValidationError(
6            "Temperature must be finite".to_string(),
7        ));
8    }
9    if value < -273.15 {
10        return Err(UnitxError::ValidationError(
11            "Temperature below absolute zero (-273.15°C)".to_string(),
12        ));
13    }
14    if value > 1e6 {
15        return Err(UnitxError::ValidationError(
16            "Temperature too high (max 1,000,000)".to_string(),
17        ));
18    }
19    Ok(())
20}
21
22pub fn validate_distance_value(value: f64) -> Result<(), UnitxError> {
23    if !value.is_finite() {
24        return Err(UnitxError::ValidationError(
25            "Distance must be finite".to_string(),
26        ));
27    }
28    if value < 0.0 {
29        return Err(UnitxError::ValidationError(
30            "Distance cannot be negative".to_string(),
31        ));
32    }
33    if value > 1e12 {
34        return Err(UnitxError::ValidationError(
35            "Distance too large (max 1 trillion)".to_string(),
36        ));
37    }
38    Ok(())
39}
40
41pub fn validate_currency_value(value: &str) -> Result<(), UnitxError> {
42    use rust_decimal::Decimal;
43    use std::str::FromStr;
44
45    if value.is_empty() {
46        return Err(UnitxError::ValidationError(
47            "Currency amount cannot be empty".to_string(),
48        ));
49    }
50
51    if value.len() > 20 {
52        return Err(UnitxError::ValidationError(
53            "Currency amount too long (max 20 chars)".to_string(),
54        ));
55    }
56
57    match Decimal::from_str(value) {
58        Ok(decimal) => {
59            if decimal < Decimal::ZERO {
60                Err(UnitxError::ValidationError(
61                    "Currency amount cannot be negative".to_string(),
62                ))
63            } else if decimal > Decimal::from(1_000_000_000i64) {
64                Err(UnitxError::ValidationError(
65                    "Currency amount too large (max 1 billion)".to_string(),
66                ))
67            } else {
68                Ok(())
69            }
70        }
71        Err(_) => Err(UnitxError::ValidationError(
72            "Invalid currency amount format".to_string(),
73        )),
74    }
75}
76
77pub fn validate_unit_string(unit: &str, category: &str) -> Result<(), UnitxError> {
78    if unit.is_empty() {
79        return Err(UnitxError::ValidationError(format!(
80            "{} unit cannot be empty",
81            category
82        )));
83    }
84    if unit.len() > 10 {
85        return Err(UnitxError::ValidationError(format!(
86            "{} unit too long (max 10 chars)",
87            category
88        )));
89    }
90    if !unit.chars().all(|c| c.is_ascii_alphabetic()) {
91        return Err(UnitxError::ValidationError(format!(
92            "{} unit must contain only letters",
93            category
94        )));
95    }
96    Ok(())
97}