Compare commits

...

2 Commits

Author SHA1 Message Date
Juhani Krekelä 897f87a9e2 Make unit constants const in conversion.rs 2023-06-01 19:58:18 +03:00
Juhani Krekelä 18ef6c8787 Fix clippy lints 2023-06-01 19:55:09 +03:00
5 changed files with 90 additions and 90 deletions

View File

@ -14,65 +14,65 @@ struct Conversion {
} }
fn get_conversion(unit: NonMetric) -> Conversion { fn get_conversion(unit: NonMetric) -> Conversion {
let inch_from = 10_000.0; const INCH_FROM: f64 = 10_000.0;
let inch_to = 254.0; const INCH_TO: f64 = 254.0;
let pound_from = 100_000.0; const POUND_FROM: f64 = 100_000.0;
let pound_to = 45359237.0; const POUND_TO: f64 = 45359237.0;
let imperial_gallon_from = 100_000.0; const IMPERIAL_GALLON_FROM: f64 = 100_000.0;
let imperial_gallon_to = 454609.0; const IMPERIAL_GALLON_TO: f64 = 454609.0;
let us_gallon_from = inch_from * inch_from * inch_from; const US_GALLON_FROM: f64 = INCH_FROM * INCH_FROM * INCH_FROM;
let us_gallon_to = 231.0 * inch_to * inch_to * inch_to * 1000.0; const US_GALLON_TO: f64 = 231.0 * INCH_TO * INCH_TO * INCH_TO * 1000.0;
match unit { match unit {
// Length // Length
NonMetric::Inch => Conversion { NonMetric::Inch => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from, from: INCH_FROM,
to: MetricQuantity { amount: inch_to, unit: Metric::Metre }, to: MetricQuantity { amount: INCH_TO, unit: Metric::Metre },
}, },
NonMetric::Foot => Conversion { NonMetric::Foot => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from, from: INCH_FROM,
to: MetricQuantity { amount: 12.0 * inch_to, unit: Metric::Metre }, to: MetricQuantity { amount: 12.0 * INCH_TO, unit: Metric::Metre },
}, },
NonMetric::Yard => Conversion { NonMetric::Yard => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from, from: INCH_FROM,
to: MetricQuantity { amount: 3.0 * 12.0 * inch_to, unit: Metric::Metre }, to: MetricQuantity { amount: 3.0 * 12.0 * INCH_TO, unit: Metric::Metre },
}, },
NonMetric::Mile => Conversion { NonMetric::Mile => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from, from: INCH_FROM,
to: MetricQuantity { amount: 1760.0 * 3.0 * 12.0 * inch_to, unit: Metric::Metre }, to: MetricQuantity { amount: 1760.0 * 3.0 * 12.0 * INCH_TO, unit: Metric::Metre },
}, },
// Mass // Mass
NonMetric::Ounce => Conversion { NonMetric::Ounce => Conversion {
offset: 0.0, offset: 0.0,
from: 16.0 * pound_from, from: 16.0 * POUND_FROM,
to: MetricQuantity { amount: pound_to, unit: Metric::Gram }, to: MetricQuantity { amount: POUND_TO, unit: Metric::Gram },
}, },
NonMetric::Pound => Conversion { NonMetric::Pound => Conversion {
offset: 0.0, offset: 0.0,
from: pound_from, from: POUND_FROM,
to: MetricQuantity { amount: pound_to, unit: Metric::Gram }, to: MetricQuantity { amount: POUND_TO, unit: Metric::Gram },
}, },
NonMetric::Stone => Conversion { NonMetric::Stone => Conversion {
offset: 0.0, offset: 0.0,
from: pound_from, from: POUND_FROM,
to: MetricQuantity { amount: 14.0 * pound_to, unit: Metric::Gram }, to: MetricQuantity { amount: 14.0 * POUND_TO, unit: Metric::Gram },
}, },
NonMetric::ShortTon => Conversion { NonMetric::ShortTon => Conversion {
offset: 0.0, offset: 0.0,
from: pound_from, from: POUND_FROM,
to: MetricQuantity { amount: 2000.0 * pound_to, unit: Metric::Gram }, to: MetricQuantity { amount: 2000.0 * POUND_TO, unit: Metric::Gram },
}, },
NonMetric::LongTon => Conversion { NonMetric::LongTon => Conversion {
offset: 0.0, offset: 0.0,
from: pound_from, from: POUND_FROM,
to: MetricQuantity { amount: 2240.0 * pound_to, unit: Metric::Gram }, to: MetricQuantity { amount: 2240.0 * POUND_TO, unit: Metric::Gram },
}, },
// Temperature // Temperature
NonMetric::Fahrenheit => Conversion { NonMetric::Fahrenheit => Conversion {
@ -83,100 +83,100 @@ fn get_conversion(unit: NonMetric) -> Conversion {
// Area // Area
NonMetric::SquareInch => Conversion { NonMetric::SquareInch => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from, from: INCH_FROM * INCH_FROM,
to: MetricQuantity { amount: inch_to * inch_to, unit: Metric::SquareMetre }, to: MetricQuantity { amount: INCH_TO * INCH_TO, unit: Metric::SquareMetre },
}, },
NonMetric::SquareFoot => Conversion { NonMetric::SquareFoot => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from, from: INCH_FROM * INCH_FROM,
to: MetricQuantity { amount: 12.0 * inch_to * 12.0 * inch_to, unit: Metric::SquareMetre }, to: MetricQuantity { amount: 12.0 * INCH_TO * 12.0 * INCH_TO, unit: Metric::SquareMetre },
}, },
NonMetric::SquareYard => Conversion { NonMetric::SquareYard => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from, from: INCH_FROM * INCH_FROM,
to: MetricQuantity { amount: 3.0 * 12.0 * inch_to * 3.0 * 12.0 * inch_to, unit: Metric::SquareMetre }, to: MetricQuantity { amount: 3.0 * 12.0 * INCH_TO * 3.0 * 12.0 * INCH_TO, unit: Metric::SquareMetre },
}, },
NonMetric::Acre => Conversion { NonMetric::Acre => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from, from: INCH_FROM * INCH_FROM,
to: MetricQuantity { amount: 43_560.0 * 12.0 * inch_to * 12.0 * inch_to, unit: Metric::SquareMetre }, to: MetricQuantity { amount: 43_560.0 * 12.0 * INCH_TO * 12.0 * INCH_TO, unit: Metric::SquareMetre },
}, },
NonMetric::SquareMile => Conversion { NonMetric::SquareMile => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from, 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 }, to: MetricQuantity { amount: 1760.0 * 3.0 * 12.0 * INCH_TO * 1760.0 * 3.0 * 12.0 * INCH_TO, unit: Metric::SquareMetre },
}, },
// Volume // Volume
NonMetric::CubicInch => Conversion { NonMetric::CubicInch => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from * inch_from, from: INCH_FROM * INCH_FROM * INCH_FROM,
to: MetricQuantity { amount: inch_to * inch_to * inch_to, unit: Metric::CubicMetre }, to: MetricQuantity { amount: INCH_TO * INCH_TO * INCH_TO, unit: Metric::CubicMetre },
}, },
NonMetric::CubicFoot => Conversion { NonMetric::CubicFoot => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from * inch_from, from: INCH_FROM * INCH_FROM * INCH_FROM,
to: MetricQuantity { amount: 12.0 * inch_to * 12.0 * inch_to * 12.0 * inch_to, unit: Metric::CubicMetre }, to: MetricQuantity { amount: 12.0 * INCH_TO * 12.0 * INCH_TO * 12.0 * INCH_TO, unit: Metric::CubicMetre },
}, },
NonMetric::CubicYard => Conversion { NonMetric::CubicYard => Conversion {
offset: 0.0, offset: 0.0,
from: inch_from * inch_from * inch_from, from: INCH_FROM * INCH_FROM * INCH_FROM,
to: MetricQuantity { amount: 3.0 * 12.0 * inch_to * 3.0 * 12.0 * inch_to * 3.0 * 12.0 * inch_to, unit: Metric::CubicMetre }, to: MetricQuantity { amount: 3.0 * 12.0 * INCH_TO * 3.0 * 12.0 * INCH_TO * 3.0 * 12.0 * INCH_TO, unit: Metric::CubicMetre },
}, },
// Fluid volume // Fluid volume
NonMetric::ImperialFluidOunce => Conversion { NonMetric::ImperialFluidOunce => Conversion {
offset: 0.0, offset: 0.0,
from: 20.0 * 2.0 * 4.0 * imperial_gallon_from, from: 20.0 * 2.0 * 4.0 * IMPERIAL_GALLON_FROM,
to: MetricQuantity { amount: imperial_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: IMPERIAL_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::ImperialPint => Conversion { NonMetric::ImperialPint => Conversion {
offset: 0.0, offset: 0.0,
from: 2.0 * 4.0 * imperial_gallon_from, from: 2.0 * 4.0 * IMPERIAL_GALLON_FROM,
to: MetricQuantity { amount: imperial_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: IMPERIAL_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::ImperialQuart => Conversion { NonMetric::ImperialQuart => Conversion {
offset: 0.0, offset: 0.0,
from: 4.0 * imperial_gallon_from, from: 4.0 * IMPERIAL_GALLON_FROM,
to: MetricQuantity { amount: imperial_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: IMPERIAL_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::ImperialGallon => Conversion { NonMetric::ImperialGallon => Conversion {
offset: 0.0, offset: 0.0,
from: imperial_gallon_from, from: IMPERIAL_GALLON_FROM,
to: MetricQuantity { amount: imperial_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: IMPERIAL_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::USTeaspoon => Conversion { NonMetric::USTeaspoon => Conversion {
offset: 0.0, offset: 0.0,
from: 6.0 * 16.0 * 2.0 * 4.0 * us_gallon_from, from: 6.0 * 16.0 * 2.0 * 4.0 * US_GALLON_FROM,
to: MetricQuantity { amount: us_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: US_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::USTablespoon => Conversion { NonMetric::USTablespoon => Conversion {
offset: 0.0, offset: 0.0,
from: 2.0 * 16.0 * 2.0 * 4.0 * us_gallon_from, from: 2.0 * 16.0 * 2.0 * 4.0 * US_GALLON_FROM,
to: MetricQuantity { amount: us_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: US_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::USFluidOunce => Conversion { NonMetric::USFluidOunce => Conversion {
offset: 0.0, offset: 0.0,
from: 16.0 * 2.0 * 4.0 * us_gallon_from, from: 16.0 * 2.0 * 4.0 * US_GALLON_FROM,
to: MetricQuantity { amount: us_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: US_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::USCup => Conversion { NonMetric::USCup => Conversion {
offset: 0.0, offset: 0.0,
from: 2.0 * 2.0 * 4.0 * us_gallon_from, from: 2.0 * 2.0 * 4.0 * US_GALLON_FROM,
to: MetricQuantity { amount: us_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: US_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::USLiquidPint => Conversion { NonMetric::USLiquidPint => Conversion {
offset: 0.0, offset: 0.0,
from: 2.0 * 4.0 * us_gallon_from, from: 2.0 * 4.0 * US_GALLON_FROM,
to: MetricQuantity { amount: us_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: US_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::USLiquidQuart => Conversion { NonMetric::USLiquidQuart => Conversion {
offset: 0.0, offset: 0.0,
from: 4.0 * us_gallon_from, from: 4.0 * US_GALLON_FROM,
to: MetricQuantity { amount: us_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: US_GALLON_TO, unit: Metric::Litre },
}, },
NonMetric::USGallon => Conversion { NonMetric::USGallon => Conversion {
offset: 0.0, offset: 0.0,
from: us_gallon_from, from: US_GALLON_FROM,
to: MetricQuantity { amount: us_gallon_to, unit: Metric::Litre }, to: MetricQuantity { amount: US_GALLON_TO, unit: Metric::Litre },
}, },
} }
} }

View File

@ -51,7 +51,7 @@ fn format_number(number: f64) -> String {
// Remove trailing zeroes // Remove trailing zeroes
let decimal = decimal.trim_end_matches('0'); let decimal = decimal.trim_end_matches('0');
if decimal.len() == 0 { if decimal.is_empty() {
format!("{sign}{grouped}") format!("{sign}{grouped}")
} else { } else {
format!("{sign}{grouped}.{decimal}") format!("{sign}{grouped}.{decimal}")
@ -67,54 +67,54 @@ fn prefixed_unit(quantity: MetricQuantity) -> PrefixedUnit {
match quantity.unit { match quantity.unit {
Metric::Metre => { Metric::Metre => {
if absolute >= 1000.0 { if absolute >= 1000.0 {
return PrefixedUnit(1000.0, "km"); PrefixedUnit(1000.0, "km")
} else if absolute >= 1.0 { } else if absolute >= 1.0 {
return PrefixedUnit(1.0, "m"); PrefixedUnit(1.0, "m")
} else if absolute >= 0.01 { } else if absolute >= 0.01 {
return PrefixedUnit(0.01, "cm"); PrefixedUnit(0.01, "cm")
} else { } else {
return PrefixedUnit(0.001, "mm"); PrefixedUnit(0.001, "mm")
} }
} }
Metric::Gram => { Metric::Gram => {
if absolute >= 1000.0 { if absolute >= 1000.0 {
return PrefixedUnit(1000.0, "kg"); PrefixedUnit(1000.0, "kg")
} else { } else {
return PrefixedUnit(1.0, "g"); PrefixedUnit(1.0, "g")
} }
} }
Metric::Celsius => PrefixedUnit(1.0, "°C"), Metric::Celsius => PrefixedUnit(1.0, "°C"),
Metric::SquareMetre => { Metric::SquareMetre => {
if absolute >= 1000.0 * 1000.0 { if absolute >= 1000.0 * 1000.0 {
return PrefixedUnit(1000.0 * 1000.0, "km²"); PrefixedUnit(1000.0 * 1000.0, "km²")
} else if absolute >= 1.0 { } else if absolute >= 1.0 {
return PrefixedUnit(1.0, ""); PrefixedUnit(1.0, "")
} else if absolute >= 0.01 * 0.01 { } else if absolute >= 0.01 * 0.01 {
return PrefixedUnit(0.01 * 0.01, "cm²"); PrefixedUnit(0.01 * 0.01, "cm²")
} else { } else {
return PrefixedUnit(0.001 * 0.001, "mm²"); PrefixedUnit(0.001 * 0.001, "mm²")
} }
} }
Metric::CubicMetre => { Metric::CubicMetre => {
if absolute >= 1000.0 * 1000.0 * 1000.0 { if absolute >= 1000.0 * 1000.0 * 1000.0 {
return PrefixedUnit(1000.0 * 1000.0 * 1000.0, "km³"); PrefixedUnit(1000.0 * 1000.0 * 1000.0, "km³")
} else if absolute >= 1.0 { } else if absolute >= 1.0 {
return PrefixedUnit(1.0, ""); PrefixedUnit(1.0, "")
} else if absolute >= 0.000_001 { // 0.01 * 0.01 * 0.01 rounds wrong } else if absolute >= 0.000_001 { // 0.01 * 0.01 * 0.01 rounds wrong
return PrefixedUnit(0.000_001, "cm³"); PrefixedUnit(0.000_001, "cm³")
} else { } else {
return PrefixedUnit(0.001 * 0.001 * 0.001, "mm³"); PrefixedUnit(0.001 * 0.001 * 0.001, "mm³")
} }
} }
Metric::Litre => { Metric::Litre => {
if absolute >= 1.0 { if absolute >= 1.0 {
return PrefixedUnit(1.0, "l"); PrefixedUnit(1.0, "l")
} else if absolute >= 0.1 { } else if absolute >= 0.1 {
return PrefixedUnit(0.1, "dl"); PrefixedUnit(0.1, "dl")
} else if absolute >= 0.01 { } else if absolute >= 0.01 {
return PrefixedUnit(0.01, "cl"); PrefixedUnit(0.01, "cl")
} else { } else {
return PrefixedUnit(0.001, "ml"); PrefixedUnit(0.001, "ml")
} }
} }
} }

View File

@ -28,7 +28,7 @@ pub fn run(input: &str) -> Result<String, String> {
} }
}; };
if non_metric.len() == 0 { if non_metric.is_empty() {
return Err("Expected quantity or quantities to convert".to_string()); return Err("Expected quantity or quantities to convert".to_string());
} }
@ -59,7 +59,7 @@ pub fn run(input: &str) -> Result<String, String> {
let amount = metric.into_iter().map(|quantity| { quantity.amount }).sum(); let amount = metric.into_iter().map(|quantity| { quantity.amount }).sum();
let quantity = MetricQuantity { let quantity = MetricQuantity {
amount: amount, amount,
unit: metric_unit.expect("we must have at least one quantity by this point"), unit: metric_unit.expect("we must have at least one quantity by this point"),
}; };

View File

@ -10,7 +10,7 @@ fn main() {
let args = args[1..].join(" "); let args = args[1..].join(" ");
if args.len() == 0 { if args.is_empty() {
loop { loop {
print!("> "); print!("> ");
match io::stdout().flush() { match io::stdout().flush() {
@ -28,7 +28,7 @@ fn main() {
process::exit(1); process::exit(1);
} }
} }
if input.len() == 0 { if input.is_empty() {
println!(); // Add a newline if user pressed ^D println!(); // Add a newline if user pressed ^D
break; break;
} }

View File

@ -36,7 +36,7 @@ pub fn parse(input: &str) -> Result<Vec<NonMetricQuantity>, ParseError> {
let unit = parse_unit(unit)?; let unit = parse_unit(unit)?;
let quantity = NonMetricQuantity { let quantity = NonMetricQuantity {
amount: amount.take().expect("must have read a number to be in this state"), amount: amount.take().expect("must have read a number to be in this state"),
unit: unit, unit,
}; };
quantities.push(quantity); quantities.push(quantity);
state = Expect::Number; state = Expect::Number;
@ -56,7 +56,7 @@ pub fn parse(input: &str) -> Result<Vec<NonMetricQuantity>, ParseError> {
fn parse_number(input: String) -> Result<f64, ParseError> { fn parse_number(input: String) -> Result<f64, ParseError> {
let no_whitespace: String = input.chars().filter(|c| !c.is_whitespace()).collect(); let no_whitespace: String = input.chars().filter(|c| !c.is_whitespace()).collect();
no_whitespace.parse().or_else(|_| Err(ParseError::NotValidNumber(input))) no_whitespace.parse().map_err(|_| ParseError::NotValidNumber(input))
} }
fn parse_unit(input: String) -> Result<NonMetric, ParseError> { fn parse_unit(input: String) -> Result<NonMetric, ParseError> {
@ -411,7 +411,7 @@ fn tokenize(input: &str) -> Vec<Token> {
} }
match state { match state {
TokState::Neutral => { assert!(token.len() == 0); } TokState::Neutral => { assert!(token.is_empty()); }
TokState::Number => { tokens.push(Token::Number(token.trim().to_string())); } TokState::Number => { tokens.push(Token::Number(token.trim().to_string())); }
TokState::Unit(_) => { tokens.push(Token::Unit(token.trim().to_string())); } TokState::Unit(_) => { tokens.push(Token::Unit(token.trim().to_string())); }
} }