diff --git a/src/conversions.rs b/src/conversions.rs index 421f5fa..511dd93 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -85,6 +85,12 @@ fn get_conversion(unit: NonMetric) -> Conversion { from: inch_from * inch_from, to: MetricQuantity { amount: 1760.0 * 3.0 * 12.0 * inch_to * 1760.0 * 3.0 * 12.0 * inch_to, unit: Metric::SquareMetre }, }, + // Volume + NonMetric::CubicInch => Conversion { + offset: 0.0, + from: inch_from * inch_from * inch_from, + to: MetricQuantity { amount: inch_to * inch_to * inch_to, unit: Metric::CubicMetre }, + }, } } @@ -144,6 +150,14 @@ mod test { run_tests(&tests, Metric::SquareMetre); } + #[test] + fn volume() { + let tests = [ + Test(NonMetric::CubicInch, 1.6387064e-5), + ]; + run_tests(&tests, Metric::CubicMetre); + } + 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 e4601f6..7e9d197 100644 --- a/src/format.rs +++ b/src/format.rs @@ -95,6 +95,17 @@ fn prefixed_unit(quantity: MetricQuantity) -> PrefixedUnit { return PrefixedUnit(0.001 * 0.001, "mm²"); } } + Metric::CubicMetre => { + if absolute >= 1000.0 * 1000.0 * 1000.0 { + return PrefixedUnit(1000.0 * 1000.0 * 1000.0, "km³"); + } else if absolute >= 1.0 { + return PrefixedUnit(1.0, "m³"); + } else if absolute >= 0.000_001 { // 0.01 * 0.01 * 0.01 rounds wrong + return PrefixedUnit(0.000_001, "cm³"); + } else { + return PrefixedUnit(0.001 * 0.001 * 0.001, "mm³"); + } + } } } @@ -341,4 +352,44 @@ mod test { unit: Metric::SquareMetre, })); } + + #[test] + fn cubic_metres() { + assert_eq!(PrefixedUnit(0.000_000_001, "mm³"), prefixed_unit(MetricQuantity { + amount: 0.000_000_000_1, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(0.000_000_001, "mm³"), prefixed_unit(MetricQuantity { + amount: 0.000_000_001, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(0.000_000_001, "mm³"), prefixed_unit(MetricQuantity { + amount: 0.000_000_1, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(0.000_001, "cm³"), prefixed_unit(MetricQuantity { + amount: 0.000_001, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(0.000_001, "cm³"), prefixed_unit(MetricQuantity { + amount: 0.1, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m³"), prefixed_unit(MetricQuantity { + amount: 1.0, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(1.0, "m³"), prefixed_unit(MetricQuantity { + amount: 100_000_000.0, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(1_000_000_000.0, "km³"), prefixed_unit(MetricQuantity { + amount: 1_000_000_000.0, + unit: Metric::CubicMetre, + })); + assert_eq!(PrefixedUnit(1_000_000_000.0, "km³"), prefixed_unit(MetricQuantity { + amount: 10_000_000_000.0, + unit: Metric::CubicMetre, + })); + } } diff --git a/src/lib.rs b/src/lib.rs index d89ff75..fc8f922 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,6 +81,8 @@ fn unit_to_name(unit: NonMetric) -> &'static str { NonMetric::SquareFoot => "square feet", NonMetric::Acre => "acres", NonMetric::SquareMile => "square miles", + // Volume + NonMetric::CubicInch => "cubic inches", } } @@ -119,5 +121,7 @@ mod test { assert_eq!(run("1 ft²"), Ok("929 cm²".to_string())); assert_eq!(run("1 acre"), Ok("4 047 m²".to_string())); assert_eq!(run("1 mi²"), Ok("2.59 km²".to_string())); + // Volume + assert_eq!(run("1 in³"), Ok("16.39 cm³".to_string())); } } diff --git a/src/parse.rs b/src/parse.rs index 2faef00..19a208a 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -158,6 +158,20 @@ fn parse_unit(input: String) -> Result { "miles^2" => Ok(NonMetric::SquareMile), "mi^2" => Ok(NonMetric::SquareMile), + // Volume + "cubic inch" => Ok(NonMetric::CubicInch), + "cubic inches" => Ok(NonMetric::CubicInch), + "cubic in" => Ok(NonMetric::CubicInch), + "cu inch" => Ok(NonMetric::CubicInch), + "cu inches" => Ok(NonMetric::CubicInch), + "cu in" => Ok(NonMetric::CubicInch), + "inch³" => Ok(NonMetric::CubicInch), + "inches³" => Ok(NonMetric::CubicInch), + "in³" => Ok(NonMetric::CubicInch), + "inch^3" => Ok(NonMetric::CubicInch), + "inches^3" => Ok(NonMetric::CubicInch), + "in^3" => Ok(NonMetric::CubicInch), + _ => Err(ParseError::UnknownUnit(input)), } } @@ -365,6 +379,20 @@ mod test { assert_eq!(parse_unit("miles^2".to_string()), Ok(NonMetric::SquareMile)); assert_eq!(parse_unit("mi^2".to_string()), Ok(NonMetric::SquareMile)); + // Volume + assert_eq!(parse_unit("cubic inch".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("cubic inches".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("cubic in".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("cu inch".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("cu inches".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("cu in".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("inch³".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("inches³".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("in³".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("inch^3".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("inches^3".to_string()), Ok(NonMetric::CubicInch)); + assert_eq!(parse_unit("in^3".to_string()), Ok(NonMetric::CubicInch)); + // 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 cdd41fd..e8cbc26 100644 --- a/src/units.rs +++ b/src/units.rs @@ -4,6 +4,7 @@ pub enum Metric { Gram, Celsius, SquareMetre, + CubicMetre, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -24,6 +25,8 @@ pub enum NonMetric { SquareFoot, Acre, SquareMile, + // Volume + CubicInch, } #[derive(Clone, Copy, Debug, PartialEq)]