Suggest disambiguations for ambiguous units
This commit is contained in:
parent
e2e1349913
commit
f354fbe555
|
@ -23,6 +23,9 @@ pub fn run(input: &str) -> Result<String, String> {
|
||||||
Err(ParseError::ExpectedUnit) => {
|
Err(ParseError::ExpectedUnit) => {
|
||||||
return Err("Expected a unit".to_string());
|
return Err("Expected a unit".to_string());
|
||||||
}
|
}
|
||||||
|
Err(ParseError::AmbiguousUnit(unit, prefix1, prefix2)) => {
|
||||||
|
return Err(format!("Ambiguous unit '{unit}', use either '{prefix1} {unit}' or '{prefix2} {unit}'"));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if non_metric.len() == 0 {
|
if non_metric.len() == 0 {
|
||||||
|
@ -110,6 +113,7 @@ mod test {
|
||||||
assert_eq!(run("1 tf"), Err("Unknown unit: tf".to_string()));
|
assert_eq!(run("1 tf"), Err("Unknown unit: tf".to_string()));
|
||||||
assert_eq!(run("1"), Err("Expected a unit".to_string()));
|
assert_eq!(run("1"), Err("Expected a unit".to_string()));
|
||||||
assert_eq!(run(""), Err("Expected quantity or quantities to convert".to_string()));
|
assert_eq!(run(""), Err("Expected quantity or quantities to convert".to_string()));
|
||||||
|
assert_eq!(run("1 fl oz"), Err("Ambiguous unit 'fl oz', use either 'imp fl oz' or 'US fl oz'".to_string()));
|
||||||
assert_eq!(run("6 ft 1 lbs"), Err("Incompatible units: feet, pounds".to_string()));
|
assert_eq!(run("6 ft 1 lbs"), Err("Incompatible units: feet, pounds".to_string()));
|
||||||
assert_eq!(run("0 °F 0 °F"), Err("Cannot sum together temperatures".to_string()));
|
assert_eq!(run("0 °F 0 °F"), Err("Cannot sum together temperatures".to_string()));
|
||||||
}
|
}
|
||||||
|
|
130
src/parse.rs
130
src/parse.rs
|
@ -11,6 +11,7 @@ pub enum ParseError {
|
||||||
UnexpectedUnit(String),
|
UnexpectedUnit(String),
|
||||||
UnknownUnit(String),
|
UnknownUnit(String),
|
||||||
ExpectedUnit,
|
ExpectedUnit,
|
||||||
|
AmbiguousUnit(String, &'static str, &'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(input: &str) -> Result<Vec<NonMetricQuantity>, ParseError> {
|
pub fn parse(input: &str) -> Result<Vec<NonMetricQuantity>, ParseError> {
|
||||||
|
@ -280,6 +281,27 @@ fn parse_unit(input: String) -> Result<NonMetric, ParseError> {
|
||||||
"us gallons" => Ok(NonMetric::USGallon),
|
"us gallons" => Ok(NonMetric::USGallon),
|
||||||
"us gal" => Ok(NonMetric::USGallon),
|
"us gal" => Ok(NonMetric::USGallon),
|
||||||
|
|
||||||
|
// Ambiguous units
|
||||||
|
"fluid ounce" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"fluid ounces" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"fl oz" => Err(ParseError::AmbiguousUnit(input, "imp", "US")),
|
||||||
|
"fl. oz." => Err(ParseError::AmbiguousUnit(input, "imp", "US")),
|
||||||
|
"oz. fl." => Err(ParseError::AmbiguousUnit(input, "imp", "US")),
|
||||||
|
|
||||||
|
"pint" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"pints" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"pt" => Err(ParseError::AmbiguousUnit(input, "imp", "US")),
|
||||||
|
"p" => Err(ParseError::AmbiguousUnit(input, "imp", "US")),
|
||||||
|
|
||||||
|
"quart" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"quarts" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"qt" => Err(ParseError::AmbiguousUnit(input, "imp", "US")),
|
||||||
|
|
||||||
|
"gallon" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"gallons" => Err(ParseError::AmbiguousUnit(input, "imperial", "US")),
|
||||||
|
"gal" => Err(ParseError::AmbiguousUnit(input, "imp", "US")),
|
||||||
|
|
||||||
|
// Unknown unit
|
||||||
_ => Err(ParseError::UnknownUnit(input)),
|
_ => Err(ParseError::UnknownUnit(input)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,6 +396,7 @@ mod test {
|
||||||
assert_eq!(parse("ft"), Err(ParseError::UnexpectedUnit("ft".to_string())));
|
assert_eq!(parse("ft"), Err(ParseError::UnexpectedUnit("ft".to_string())));
|
||||||
assert_eq!(parse("5 tf"), Err(ParseError::UnknownUnit("tf".to_string())));
|
assert_eq!(parse("5 tf"), Err(ParseError::UnknownUnit("tf".to_string())));
|
||||||
assert_eq!(parse("12"), Err(ParseError::ExpectedUnit));
|
assert_eq!(parse("12"), Err(ParseError::ExpectedUnit));
|
||||||
|
assert_eq!(parse("1 gallon"), Err(ParseError::AmbiguousUnit("gallon".to_string(), "imperial", "US")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -608,8 +631,113 @@ mod test {
|
||||||
assert_eq!(parse_unit("us gallon".to_string()), Ok(NonMetric::USGallon));
|
assert_eq!(parse_unit("us gallon".to_string()), Ok(NonMetric::USGallon));
|
||||||
assert_eq!(parse_unit("us gallons".to_string()), Ok(NonMetric::USGallon));
|
assert_eq!(parse_unit("us gallons".to_string()), Ok(NonMetric::USGallon));
|
||||||
assert_eq!(parse_unit("us gal".to_string()), Ok(NonMetric::USGallon));
|
assert_eq!(parse_unit("us gal".to_string()), Ok(NonMetric::USGallon));
|
||||||
|
}
|
||||||
|
|
||||||
// Unknown unit
|
#[test]
|
||||||
|
fn ambiguous_units() {
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("fluid ounce".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("fluid ounce".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("fluid ounces".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("fluid ounces".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("fl oz".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("fl oz".to_string(), "imp", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("fl. oz.".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("fl. oz.".to_string(), "imp", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("oz. fl.".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("oz. fl.".to_string(), "imp", "US"))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("pint".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("pint".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("pints".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("pints".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("pt".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("pt".to_string(), "imp", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("p".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("p".to_string(), "imp", "US"))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("quart".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("quart".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("quarts".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("quarts".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("qt".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("qt".to_string(), "imp", "US"))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("gallon".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("gallon".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("gallons".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("gallons".to_string(), "imperial", "US"))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_unit("gal".to_string()),
|
||||||
|
Err(ParseError::AmbiguousUnit("gal".to_string(), "imp", "US"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ambiguous_unit_suggestions() {
|
||||||
|
let ambiguous_units = [
|
||||||
|
"fluid ounce",
|
||||||
|
"fluid ounces",
|
||||||
|
"fl oz",
|
||||||
|
"fl. oz.",
|
||||||
|
"oz. fl.",
|
||||||
|
|
||||||
|
"pint",
|
||||||
|
"pints",
|
||||||
|
"pt",
|
||||||
|
"p",
|
||||||
|
|
||||||
|
"quart",
|
||||||
|
"quarts",
|
||||||
|
"qt",
|
||||||
|
|
||||||
|
"gallon",
|
||||||
|
"gallons",
|
||||||
|
"gal",
|
||||||
|
];
|
||||||
|
|
||||||
|
for unit in ambiguous_units {
|
||||||
|
let parsed = parse_unit(unit.to_string());
|
||||||
|
if let Err(ParseError::AmbiguousUnit(unit, prefix1, prefix2)) = parsed {
|
||||||
|
let suggestion1 = format!("{prefix1} {unit}");
|
||||||
|
let suggestion2 = format!("{prefix2} {unit}");
|
||||||
|
assert!(parse_unit(suggestion1).is_ok());
|
||||||
|
assert!(parse_unit(suggestion2).is_ok());
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_unit() {
|
||||||
assert_eq!(parse_unit("hutenosa".to_string()), Err(ParseError::UnknownUnit("hutenosa".to_string())));
|
assert_eq!(parse_unit("hutenosa".to_string()), Err(ParseError::UnknownUnit("hutenosa".to_string())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue