diff --git a/src/conversions.rs b/src/conversions.rs index c6c1006..79e8fb6 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -64,6 +64,12 @@ fn get_conversion(unit: NonMetric) -> Conversion { from: 9.0, to: MetricQuantity { amount: 5.0, unit: Metric::Celcius }, }, + // Area + NonMetric::SquareInch => Conversion { + offset: 0.0, + from: inch_from * inch_from, + to: MetricQuantity { amount: inch_to * inch_to, unit: Metric::SquareMetre }, + }, } } @@ -112,6 +118,14 @@ mod test { }); } + #[test] + fn area() { + let tests = [ + Test(NonMetric::SquareInch, 0.00064516), + ]; + run_tests(&tests, Metric::SquareMetre); + } + fn run_tests(tests: &[Test], unit: Metric) { for test in tests { let from = NonMetricQuantity { diff --git a/src/format.rs b/src/format.rs index f0039f3..d19f6cb 100644 --- a/src/format.rs +++ b/src/format.rs @@ -84,6 +84,17 @@ fn prefixed_unit(quantity: MetricQuantity) -> PrefixedUnit { } } Metric::Celcius => PrefixedUnit(1.0, "°C"), + Metric::SquareMetre => { + if absolute >= 1000.0 * 1000.0 { + return PrefixedUnit(1000.0 * 1000.0, "km²"); + } else if absolute >= 1.0 { + return PrefixedUnit(1.0, "m²"); + } else if absolute >= 0.01 * 0.01 { + return PrefixedUnit(0.01 * 0.01, "cm²"); + } else { + return PrefixedUnit(0.001 * 0.001, "mm²"); + } + } } } @@ -262,4 +273,72 @@ mod test { unit: Metric::Celcius, })); } + + #[test] + fn square_metres() { + assert_eq!(PrefixedUnit(0.000_001, "mm²"), prefixed_unit(MetricQuantity { + amount: 0.000_000_1, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(0.000_001, "mm²"), prefixed_unit(MetricQuantity { + amount: 0.000_001, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(0.000_001, "mm²"), prefixed_unit(MetricQuantity { + amount: 0.000_01, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(0.000_1, "cm²"), prefixed_unit(MetricQuantity { + amount: 0.000_1, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(0.000_1, "cm²"), prefixed_unit(MetricQuantity { + amount: 0.001, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(0.000_1, "cm²"), prefixed_unit(MetricQuantity { + amount: 0.01, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(0.000_1, "cm²"), prefixed_unit(MetricQuantity { + amount: 0.01, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(0.000_1, "cm²"), prefixed_unit(MetricQuantity { + amount: 0.1, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m²"), prefixed_unit(MetricQuantity { + amount: 1.0, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m²"), prefixed_unit(MetricQuantity { + amount: 10.0, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m²"), prefixed_unit(MetricQuantity { + amount: 100.0, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m²"), prefixed_unit(MetricQuantity { + amount: 1_000.0, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m²"), prefixed_unit(MetricQuantity { + amount: 10_000.0, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m²"), prefixed_unit(MetricQuantity { + amount: 100_000.0, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1_000_000.0, "km²"), prefixed_unit(MetricQuantity { + amount: 1_000_000.0, + unit: Metric::SquareMetre, + })); + assert_eq!(PrefixedUnit(1_000_000.0, "km²"), prefixed_unit(MetricQuantity { + amount: 10_000_000.0, + unit: Metric::SquareMetre, + })); + } } diff --git a/src/lib.rs b/src/lib.rs index 672c4cd..c9995f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,8 @@ fn unit_to_name(unit: NonMetric) -> &'static str { NonMetric::Stone => "stones", // Temperature NonMetric::Fahrenheit => "degrees Fahrenheit", + // Area + NonMetric::SquareInch => "square inches", } } @@ -104,5 +106,7 @@ mod test { assert_eq!(run("-40 °F"), Ok("-40 °C".to_string())); assert_eq!(run("0 °F"), Ok("-17.78 °C".to_string())); assert_eq!(run("32 °F"), Ok("0 °C".to_string())); + // Area + assert_eq!(run("1 in²"), Ok("6.452 cm²".to_string())); } } diff --git a/src/parse.rs b/src/parse.rs index 8a9a958..40c4d5b 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -101,6 +101,11 @@ fn parse_unit(input: String) -> Result { "°F" => Ok(NonMetric::Fahrenheit), "F" => Ok(NonMetric::Fahrenheit), + // Area + "inch²" => Ok(NonMetric::SquareInch), + "inches²" => Ok(NonMetric::SquareInch), + "in²" => Ok(NonMetric::SquareInch), + _ => Err(ParseError::UnknownUnit(input)), } } @@ -249,6 +254,11 @@ mod test { assert_eq!(parse_unit("°F".to_string()), Ok(NonMetric::Fahrenheit)); assert_eq!(parse_unit("F".to_string()), Ok(NonMetric::Fahrenheit)); + // Area + assert_eq!(parse_unit("inch²".to_string()), Ok(NonMetric::SquareInch)); + assert_eq!(parse_unit("inches²".to_string()), Ok(NonMetric::SquareInch)); + assert_eq!(parse_unit("in²".to_string()), Ok(NonMetric::SquareInch)); + // Unknown unit assert_eq!(parse_unit("hutenosa".to_string()), Err(ParseError::UnknownUnit("hutenosa".to_string()))); } diff --git a/src/units.rs b/src/units.rs index 40a42af..df25baf 100644 --- a/src/units.rs +++ b/src/units.rs @@ -3,6 +3,7 @@ pub enum Metric { Metre, Gram, Celcius, + SquareMetre, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -18,6 +19,8 @@ pub enum NonMetric { Stone, // Temperature Fahrenheit, + // Area + SquareInch, } #[derive(Clone, Copy, Debug, PartialEq)]