Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
const LIMIT: i64 = 1_000_000_000_000;
fn micrometres(name: &str, value: i64) {
if !(-LIMIT..=LIMIT).contains(&value) {
panic!("{} must be a whole number of micrometres within ±10^12, received {}", name, value);
}
}
/// Check a measurement against nominal plus its upper and lower deviations.
///
/// The deviations are signed and independent, so a tolerance band that lies
/// wholly above or below nominal (an H7 hole, a g6 shaft) is checked
/// correctly; a symmetric band is just `+t, -t`.
///
/// # Panics
/// Panics on a value beyond ±10^12 µm, or a lower deviation above the upper.
pub fn check_tolerance(measured: i64, nominal: i64, upper_deviation: i64, lower_deviation: i64) -> ToleranceCheck {
micrometres("measured", measured);
micrometres("nominal", nominal);
micrometres("upperDeviation", upper_deviation);
micrometres("lowerDeviation", lower_deviation);
if lower_deviation > upper_deviation {
panic!(
"lowerDeviation must not be greater than upperDeviation, received {} and {}",
lower_deviation, upper_deviation
);
}
let lower_limit = nominal + lower_deviation;
let upper_limit = nominal + upper_deviation;
let deviation = measured - nominal;
let (passed, status, out_by) = if measured > upper_limit {
(false, "above", measured - upper_limit)
} else if measured < lower_limit {
(false, "below", lower_limit - measured)
} else {
(true, "within", 0)
};
ToleranceCheck {
passed,
status: status.to_string(),
deviation,
lower_limit,
upper_limit,
out_by,
}
}
pub fn tolerance_check_to_value(result: &ToleranceCheck) -> Value {
Value::obj(vec![
("passed", Value::Bool(result.passed)),
("status", Value::str(&result.status)),
("deviation", Value::Int(result.deviation)),
("lowerLimit", Value::Int(result.lower_limit)),
("upperLimit", Value::Int(result.upper_limit)),
("outBy", Value::Int(result.out_by)),
])
}
pub fn fune_vector(args: &[Value]) -> Value {
// Refuse what an i64 cannot hold, with the wording the other languages use.
let names = ["measured", "nominal", "upperDeviation", "lowerDeviation"];
for (i, name) in names.iter().enumerate() {
match &args[i] {
Value::Int(_) => {}
Value::Float(f) => panic!("{} must be a whole number of micrometres within ±10^12, received {}", name, f),
other => panic!("{} must be a whole number of micrometres within ±10^12, received {}", name, other),
}
}
tolerance_check_to_value(&check_tolerance(
args[0].as_i64(),
args[1].as_i64(),
args[2].as_i64(),
args[3].as_i64(),
))
}