danwi
A zero-cost dimensional analysis library for Rust with SI units, compile-time
type checking, and no_std support.
Usage
use *;
// dimensions combine at the type level; mismatches are compile errors
let v = 5.0.mA * 2.0.kOhm;
assert_eq!;
// convert and format in any unit of the same dimension
assert_eq!;
println!; // 10000 mV
// values are stored in SI base units, so mixed prefixes just work
let len = 100.0.m + 50.0 * cm + 0.001 * km;
assert_eq!;
// non-SI units: minute, hour, Celsius, litre, inch, ...
let temp = 25.0.celsius;
assert_eq!;
println!; // 25 °C
Custom units are one line each; the built-in set is itself a single
units! invocation:
use *;
use F64QuantityExt as _;
assert_eq!;
Some quantities share a dimension but mean different things: torque and
energy are both M·L²·T⁻². Kinds keep them apart. Every quantity has an
invisible default kind, so nothing changes until you opt in with
cast_kind; a named kind only adds and compares with itself, and must be
erased explicitly before multiplying:
use ;
let torque = .;
assert_eq!;
// torque + 5.0.J() does not compile; neither does torque / 2.0.s()
assert_eq!;
Custom kinds are one line: danwi::kinds! { Activity; }.
Getting started
[]
= "0.4"
The default scalar type is f64. For f32, enable the feature:
= { = "0.4", = ["f32"] } # both
= { = "0.4", = false, = ["f32"] } # f32 only
Import the prelude and go:
use *;
let i = 12.0.V / 4.0.kOhm;
assert_eq!;
With both scalar features enabled, an unsuffixed literal in value * unit
syntax can be ambiguous (write 10.0_f64 * V); the extension methods
(10.0.V()) never are.
Construction and conversion compile to at most one float op each, and
everything in between is plain scalar arithmetic; verify with
cargo rustc --release --example asm_check -- --emit=asm.