Initial Commit
This commit is contained in:
commit
3036856464
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
/Cargo.lock
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "units"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
typenum = "1.16"
|
172
src/lib.rs
Normal file
172
src/lib.rs
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
use std::{
|
||||||
|
marker::PhantomData,
|
||||||
|
ops::{Add, Mul},
|
||||||
|
};
|
||||||
|
|
||||||
|
use typenum::consts::*;
|
||||||
|
use typenum::{op, Integer};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||||
|
pub struct SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
||||||
|
where
|
||||||
|
Second: Integer,
|
||||||
|
Meter: Integer,
|
||||||
|
Kilogram: Integer,
|
||||||
|
Ampere: Integer,
|
||||||
|
Kelvin: Integer,
|
||||||
|
Mole: Integer,
|
||||||
|
Candela: Integer,
|
||||||
|
{
|
||||||
|
value: T,
|
||||||
|
_s: PhantomData<Second>,
|
||||||
|
_m: PhantomData<Meter>,
|
||||||
|
_kg: PhantomData<Kilogram>,
|
||||||
|
_a: PhantomData<Ampere>,
|
||||||
|
_k: PhantomData<Kelvin>,
|
||||||
|
_mol: PhantomData<Mole>,
|
||||||
|
_cd: PhantomData<Candela>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
||||||
|
SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
||||||
|
where
|
||||||
|
Second: Integer,
|
||||||
|
Meter: Integer,
|
||||||
|
Kilogram: Integer,
|
||||||
|
Ampere: Integer,
|
||||||
|
Kelvin: Integer,
|
||||||
|
Mole: Integer,
|
||||||
|
Candela: Integer,
|
||||||
|
{
|
||||||
|
pub const fn new(value: T) -> Self {
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
_s: PhantomData,
|
||||||
|
_m: PhantomData,
|
||||||
|
_kg: PhantomData,
|
||||||
|
_a: PhantomData,
|
||||||
|
_k: PhantomData,
|
||||||
|
_mol: PhantomData,
|
||||||
|
_cd: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
T,
|
||||||
|
Second1,
|
||||||
|
Meter1,
|
||||||
|
Kilogram1,
|
||||||
|
Ampere1,
|
||||||
|
Kelvin1,
|
||||||
|
Mole1,
|
||||||
|
Candela1,
|
||||||
|
Second2,
|
||||||
|
Meter2,
|
||||||
|
Kilogram2,
|
||||||
|
Ampere2,
|
||||||
|
Kelvin2,
|
||||||
|
Mole2,
|
||||||
|
Candela2,
|
||||||
|
> Mul<SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>>
|
||||||
|
for SiUnit<T, Second2, Meter2, Kilogram2, Ampere2, Kelvin2, Mole2, Candela2>
|
||||||
|
where
|
||||||
|
Mole2: Integer,
|
||||||
|
Candela2: Integer,
|
||||||
|
Candela1: Integer + Add<Candela2>,
|
||||||
|
Mole1: Integer + Add<Mole2>,
|
||||||
|
Kelvin1: Integer + Add<Kelvin2>,
|
||||||
|
Ampere1: Integer + Add<Ampere2>,
|
||||||
|
Kilogram1: Integer + Add<Kilogram2>,
|
||||||
|
Meter1: Integer + Add<Meter2>,
|
||||||
|
Second1: Integer + Add<Second2>,
|
||||||
|
Kelvin2: Integer,
|
||||||
|
Ampere2: Integer,
|
||||||
|
Kilogram2: Integer,
|
||||||
|
Meter2: Integer,
|
||||||
|
Second2: Integer,
|
||||||
|
T: Mul,
|
||||||
|
Second1::Output: Integer,
|
||||||
|
Meter1::Output: Integer,
|
||||||
|
Kilogram1::Output: Integer,
|
||||||
|
Ampere1::Output: Integer,
|
||||||
|
Kelvin1::Output: Integer,
|
||||||
|
Mole1::Output: Integer,
|
||||||
|
Candela1::Output: Integer,
|
||||||
|
{
|
||||||
|
type Output = SiUnit<
|
||||||
|
T::Output,
|
||||||
|
op!(Second1 + Second2),
|
||||||
|
op!(Meter1 + Meter2),
|
||||||
|
op!(Kilogram1 + Kilogram2),
|
||||||
|
op!(Ampere1 + Ampere2),
|
||||||
|
op!(Kelvin1 + Kelvin2),
|
||||||
|
op!(Mole1 + Mole2),
|
||||||
|
op!(Candela1 + Candela2),
|
||||||
|
>;
|
||||||
|
|
||||||
|
fn mul(
|
||||||
|
self,
|
||||||
|
rhs: SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>,
|
||||||
|
) -> Self::Output {
|
||||||
|
Self::Output::new(self.value * rhs.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
mod aliases {
|
||||||
|
use super::*;
|
||||||
|
// Base units
|
||||||
|
pub type Unit<T> = SiUnit<T, Z0, Z0, Z0, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Second<T> = SiUnit<T, P1, Z0, Z0, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Meter<T> = SiUnit<T, Z0, P1, Z0, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Kilogram<T> = SiUnit<T, Z0, Z0, P1, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Ampere<T> = SiUnit<T, Z0, Z0, Z0, P1, Z0, Z0, Z0>;
|
||||||
|
pub type Kelvin<T> = SiUnit<T, Z0, Z0, Z0, Z0, P1, Z0, Z0>;
|
||||||
|
pub type Mole<T> = SiUnit<T, Z0, Z0, Z0, Z0, Z0, P1, Z0>;
|
||||||
|
pub type Candela<T> = SiUnit<T, Z0, Z0, Z0, Z0, Z0, Z0, P1>;
|
||||||
|
|
||||||
|
// Derived units with special names
|
||||||
|
pub type Radian<T> = Unit<T>;
|
||||||
|
pub type Steradian<T> = Unit<T>;
|
||||||
|
pub type Herz<T> = SiUnit<T, N1, Z0, Z0, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Newton<T> = SiUnit<T, N2, P1, P1, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Pascal<T> = SiUnit<T, N2, N1, P1, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Joule<T> = SiUnit<T, N2, P2, P1, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Watt<T> = SiUnit<T, N3, P2, P1, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Coulomb<T> = SiUnit<T, P1, Z0, Z0, P1, Z0, Z0, Z0>;
|
||||||
|
pub type Volt<T> = SiUnit<T, N3, P2, P1, N1, Z0, Z0, Z0>;
|
||||||
|
pub type Farad<T> = SiUnit<T, P4, N2, N1, P2, Z0, Z0, Z0>;
|
||||||
|
pub type Ohm<T> = SiUnit<T, N3, P2, P1, N2, Z0, Z0, Z0>;
|
||||||
|
pub type Siemens<T> = SiUnit<T, P3, N2, N1, P2, Z0, Z0, Z0>;
|
||||||
|
pub type Weber<T> = SiUnit<T, N2, P2, P1, N1, Z0, Z0, Z0>;
|
||||||
|
pub type Tesla<T> = SiUnit<T, N2, Z0, P1, N1, Z0, Z0, Z0>;
|
||||||
|
pub type Henry<T> = SiUnit<T, N2, P2, P1, N2, Z0, Z0, Z0>;
|
||||||
|
pub type Lumen<T> = Candela<T>;
|
||||||
|
pub type Lux<T> = SiUnit<T, Z0, N2, Z0, Z0, Z0, Z0, P1>;
|
||||||
|
pub type Becquerel<T> = Herz<T>;
|
||||||
|
pub type Gray<T> = SiUnit<T, N2, P2, Z0, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type Sievert<T> = Gray<T>;
|
||||||
|
pub type Katal<T> = SiUnit<T, N1, Z0, Z0, Z0, Z0, P1, Z0>;
|
||||||
|
|
||||||
|
pub type SquareMeter<T> = SiUnit<T, Z0, P2, Z0, Z0, Z0, Z0, Z0>;
|
||||||
|
pub type CubicMeter<T> = SiUnit<T, Z0, P3, Z0, Z0, Z0, Z0, Z0>;
|
||||||
|
}
|
||||||
|
pub use aliases::*;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiply() {
|
||||||
|
let m = Meter::new(2);
|
||||||
|
assert_eq!(m * m, SquareMeter::new(4));
|
||||||
|
assert_eq!(m * m * m, CubicMeter::new(8));
|
||||||
|
let s = Second::new(1);
|
||||||
|
let a = Ampere::new(2);
|
||||||
|
assert_eq!(s * a, Coulomb::new(2));
|
||||||
|
let v = Volt::new(2);
|
||||||
|
assert_eq!(v * a, Watt::new(4));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user