4 releases
0.1.3 | Dec 14, 2023 |
---|---|
0.1.2 | Dec 14, 2023 |
0.1.1 | Dec 6, 2023 |
0.1.0 | Dec 3, 2023 |
#1058 in Rust patterns
21 downloads per month
56KB
1K
SLoC
const-units
A library that lets you validate the dimensions of your quantities at compile time and at runtime.
WARNING: Uses the experimental features generic_const_exprs
and adt_const_params
which are known to cause bugs. Disable the const
feature if you're only interested in runtime checking.
Compile time example
Okay
use const_units::si; // Parses units at compile time
use const_units::Quantity; // Represents a number with a dimension
// Input attometers, return square attometers
fn square_dist(
x: Quantity<f64, { si("am") }>,
y: Quantity<f64, { si("am") }>,
) -> Quantity<f64, { si("am^2") }> {
x.powi::<2>() + y.powi::<2>()
}
// Input attometers, return meters
fn distance(
x: Quantity<f64, { si("am") }>,
y: Quantity<f64, { si("am") }>,
) -> Quantity<f64, { si("m") }> {
square_dist(x, y)
.powf::<{ (1, 2) }>() // `(1, 2)` represents 1/2
.convert_to::<{ si("m") }>()
}
assert_eq!(
distance(Quantity(3.), Quantity(4.)),
Quantity(0.000_000_000_000_000_005)
);
Broken
# use const_units::{Quantity, units::{meter, second, DIMENSIONLESS}};
fn sum(
x: Quantity<f64, { meter }>,
y: Quantity<f64, { second }>,
) -> Quantity<f64, DIMENSIONLESS> {
x + y // You can't add meters and seconds
}
Run time example
Requires the dyn
feature
use const_units::si;
use const_units::DynQuantity; // A quantity with dynamic units stored at runtime alongside the number
use const_units::InconsistentUnits; // The error returned when inconsistent units are used together
fn distance(
x: DynQuantity<f64>,
y: DynQuantity<f64>,
) -> DynQuantity<f64> {
// The addition operator will panic if the units are inconsistent
(x.powi(2) + y.powi(2))
.powf((1, 2))
.convert_to(si("m"))
.unwrap()
}
fn distance_checked(
x: DynQuantity<f64>,
y: DynQuantity<f64>,
) -> Result<DynQuantity<f64>, InconsistentUnits> {
// You can use checked operators to avoid panicking
x.powi(2)
.checked_add(y.powi(2))?
.powf((1, 2))
.convert_to(si("m"))
}
assert_eq!(
distance_checked(DynQuantity(3., si("am")), DynQuantity(4., si("am"))),
Ok(DynQuantity(0.000_000_000_000_000_005, si("m"))),
);
assert_eq!(
distance_checked(DynQuantity(3., si("m")), DynQuantity(4., si("m"))),
Ok(DynQuantity(5., si("m"))),
);
assert!(distance_checked(DynQuantity(3., si("m")), DynQuantity(4., si("s"))).is_err());
no-std
The std
feature can be disabled to allow the crate to function in no-std environments. Doing so will remove convenience methods to convert quantities directly to strings as well as prevent errors from implementing std::error::Error
.
Dependencies
~650KB
~14K SLoC