Initial Commit
This commit is contained in:
		
							
								
								
									
										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)); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user