Skip to content

Commit edb947e

Browse files
committed
Moved fundamental equations out to lib.rs, and macroified.
1 parent a950a90 commit edb947e

File tree

11 files changed

+85
-285
lines changed

11 files changed

+85
-285
lines changed

src/acceleration.rs

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use super::measurement::*;
2-
use super::*;
3-
use std::time::Duration;
2+
use super::length;
43

54
/// The `Acceleration` struct can be used to deal with Accelerations in a common way.
65
/// Common metric and imperial units are supported.
@@ -49,33 +48,6 @@ impl Acceleration {
4948
}
5049
}
5150

52-
/// Acceleration * Time = Speed
53-
impl ::std::ops::Mul<Duration> for Acceleration {
54-
type Output = Speed;
55-
56-
fn mul(self, rhs: Duration) -> Speed {
57-
Speed::from_meters_per_second(self.as_meters_per_second_per_second() * duration_as_f64(rhs))
58-
}
59-
}
60-
61-
/// Time * Acceleration = Speed
62-
impl ::std::ops::Mul<Acceleration> for Duration {
63-
type Output = Speed;
64-
65-
fn mul(self, rhs: Acceleration) -> Speed {
66-
rhs * self
67-
}
68-
}
69-
70-
/// mass * acceleration = Force
71-
impl ::std::ops::Mul<Mass> for Acceleration {
72-
type Output = Force;
73-
74-
fn mul(self, rhs: Mass) -> Force {
75-
Force::from_newtons(rhs.as_kilograms() * self.as_meters_per_second_per_second())
76-
}
77-
}
78-
7951
impl Measurement for Acceleration {
8052
fn get_base_units(&self) -> f64 {
8153
self.meters_per_second_per_second

src/area.rs

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::measurement::*;
2-
use super::*;
2+
use super::length;
33

44
const SQUARE_METER_ACRE_FACTOR: f64 = 4046.86;
55

@@ -225,33 +225,6 @@ impl Area {
225225
}
226226
}
227227

228-
/// Area / Length = Length
229-
impl ::std::ops::Div<Length> for Area {
230-
type Output = Length;
231-
232-
fn div(self, rhs: Length) -> Length {
233-
Length::from_meters(self.as_square_meters() / rhs.as_meters())
234-
}
235-
}
236-
237-
/// Area * Length = Volume
238-
impl ::std::ops::Mul<Length> for Area {
239-
type Output = Volume;
240-
241-
fn mul(self, rhs: Length) -> Volume {
242-
Volume::from_cubic_meters(self.as_square_meters() * rhs.as_meters())
243-
}
244-
}
245-
246-
/// Area * Pressure = Force
247-
impl ::std::ops::Mul<Pressure> for Area {
248-
type Output = Force;
249-
250-
fn mul(self, rhs: Pressure) -> Force {
251-
Force::from_newtons(self.as_square_meters() * rhs.as_pascals())
252-
}
253-
}
254-
255228
impl Measurement for Area {
256229
fn get_base_units(&self) -> f64 {
257230
self.square_meters

src/energy.rs

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use super::measurement::*;
2-
use super::*;
3-
use std::time::Duration;
42

53
/// The `Energy` struct can be used to deal with energies in a common way.
64
/// Common metric and imperial units are supported.
@@ -68,44 +66,6 @@ impl Energy {
6866
}
6967
}
7068

71-
/// Energy / Time = Power
72-
impl ::std::ops::Div<Duration> for Energy {
73-
type Output = Power;
74-
75-
fn div(self, rhs: Duration) -> Power {
76-
Power::from_watts(self.as_joules() / duration_as_f64(rhs))
77-
}
78-
}
79-
80-
/// Energy / Power = Time
81-
impl ::std::ops::Div<Power> for Energy {
82-
type Output = Duration;
83-
84-
fn div(self, rhs: Power) -> Duration {
85-
let seconds = self.as_joules() / rhs.as_watts();
86-
let nanosecs = (seconds * 1e9) % 1e9;
87-
Duration::new(seconds as u64, nanosecs as u32)
88-
}
89-
}
90-
91-
/// Energy / Length = Force
92-
impl ::std::ops::Div<Length> for Energy {
93-
type Output = Force;
94-
95-
fn div(self, rhs: Length) -> Force {
96-
Force::from_newtons(self.as_joules() / rhs.as_meters())
97-
}
98-
}
99-
100-
/// Energy / Force = Length
101-
impl ::std::ops::Div<Force> for Energy {
102-
type Output = Length;
103-
104-
fn div(self, rhs: Force) -> Length {
105-
Length::from_meters(self.as_joules() / rhs.as_newtons())
106-
}
107-
}
108-
10969
impl Measurement for Energy {
11070
fn get_base_units(&self) -> f64 {
11171
self.joules

src/force.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use super::measurement::*;
2-
use super::*;
32

43
/// The `Force` struct can be used to deal with force in a common way.
54
///
@@ -89,51 +88,6 @@ impl Force {
8988
}
9089
}
9190

92-
/// Force / Mass = Acceleration
93-
impl ::std::ops::Div<Mass> for Force {
94-
type Output = Acceleration;
95-
96-
fn div(self, rhs: Mass) -> Acceleration {
97-
Acceleration::from_meters_per_second_per_second(self.as_newtons() / rhs.as_kilograms())
98-
}
99-
}
100-
101-
/// Force / Acceleration = Mass
102-
impl ::std::ops::Div<Acceleration> for Force {
103-
type Output = Mass;
104-
105-
fn div(self, rhs: Acceleration) -> Mass {
106-
Mass::from_kilograms(self.as_newtons() / rhs.as_meters_per_second_per_second())
107-
}
108-
}
109-
110-
/// Force / Area = Pressure
111-
impl ::std::ops::Div<Area> for Force {
112-
type Output = Pressure;
113-
114-
fn div(self, rhs: Area) -> Pressure {
115-
Pressure::from_pascals(self.as_newtons() / rhs.as_square_metres())
116-
}
117-
}
118-
119-
/// Force / Pressure = Area
120-
impl ::std::ops::Div<Pressure> for Force {
121-
type Output = Area;
122-
123-
fn div(self, rhs: Pressure) -> Area {
124-
Area::from_square_meters(self.as_newtons() / rhs.as_pascals())
125-
}
126-
}
127-
128-
/// Force * Length = Energy
129-
impl ::std::ops::Mul<Length> for Force {
130-
type Output = Energy;
131-
132-
fn mul(self, rhs: Length) -> Energy {
133-
Energy::from_joules(self.as_newtons() * rhs.as_meters())
134-
}
135-
}
136-
13791
impl Measurement for Force {
13892
fn get_base_units(&self) -> f64 {
13993
self.newtons

src/length.rs

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use super::measurement::*;
2-
use super::*;
3-
use std::time::Duration;
42

53
// Constants, metric
64
pub const METER_NANOMETER_FACTOR: f64 = 1000000000.0;
@@ -210,45 +208,6 @@ impl Length {
210208
}
211209
}
212210

213-
/// Length / Time = Speed
214-
impl ::std::ops::Div<Duration> for Length {
215-
type Output = Speed;
216-
217-
fn div(self, rhs: Duration) -> Speed {
218-
Speed::from_meters_per_second(self.as_meters() / duration_as_f64(rhs))
219-
}
220-
}
221-
222-
/// Length / Speed = Time
223-
impl ::std::ops::Div<Speed> for Length {
224-
type Output = Duration;
225-
226-
fn div(self, rhs: Speed) -> Duration {
227-
let seconds = self.as_meters() / rhs.as_meters_per_second();
228-
let nanosecs = (seconds * 1e9) % 1e9;
229-
Duration::new(seconds as u64, nanosecs as u32)
230-
}
231-
}
232-
233-
/// Length * Area = Volume
234-
impl ::std::ops::Mul<Area> for Length {
235-
type Output = Volume;
236-
237-
fn mul(self, rhs: Area) -> Volume {
238-
Volume::from_cubic_meters(self.as_meters() * rhs.as_square_meters())
239-
}
240-
}
241-
242-
/// Length * Force = Energy
243-
impl ::std::ops::Mul<Force> for Length {
244-
type Output = Energy;
245-
246-
fn mul(self, rhs: Force) -> Energy {
247-
Energy::from_joules(rhs.as_newtons() * self.as_meters())
248-
}
249-
}
250-
251-
252211
impl Measurement for Length {
253212
fn get_base_units(&self) -> f64 {
254213
self.meters

src/lib.rs

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,91 @@ pub use force::Force;
3535
pub mod area;
3636
pub use area::Area;
3737

38-
pub fn duration_as_f64(duration: std::time::Duration) -> f64 {
39-
duration.as_secs() as f64 + ((duration.subsec_nanos() as f64) * 1e-9)
38+
/// For given types A, B and C, implement, using base units:
39+
/// - A = B * C
40+
/// - A = C * B
41+
/// - B = A / C
42+
/// - C = A / B
43+
macro_rules! impl_maths {
44+
($a:ty, $b:ty) => {
45+
impl ::std::ops::Mul<$b> for $b {
46+
type Output = $a;
47+
48+
fn mul(self, rhs: $b) -> Self::Output {
49+
Self::Output::from_base_units(self.get_base_units() * rhs.get_base_units())
50+
}
51+
}
52+
53+
impl ::std::ops::Div<$b> for $a {
54+
type Output = $b;
55+
56+
fn div(self, rhs: $b) -> Self::Output {
57+
Self::Output::from_base_units(self.get_base_units() / rhs.get_base_units())
58+
}
59+
}
60+
};
61+
62+
($a:ty, $b:ty, $c:ty) => {
63+
impl ::std::ops::Mul<$b> for $c {
64+
type Output = $a;
65+
66+
fn mul(self, rhs: $b) -> Self::Output {
67+
Self::Output::from_base_units(self.get_base_units() * rhs.get_base_units())
68+
}
69+
}
70+
71+
impl ::std::ops::Mul<$c> for $b {
72+
type Output = $a;
73+
74+
fn mul(self, rhs: $c) -> Self::Output {
75+
Self::Output::from_base_units(self.get_base_units() * rhs.get_base_units())
76+
}
77+
}
78+
79+
impl ::std::ops::Div<$c> for $a {
80+
type Output = $b;
81+
82+
fn div(self, rhs: $c) -> Self::Output {
83+
Self::Output::from_base_units(self.get_base_units() / rhs.get_base_units())
84+
}
85+
}
86+
87+
impl ::std::ops::Div<$b> for $a {
88+
type Output = $c;
89+
90+
fn div(self, rhs: $b) -> Self::Output {
91+
Self::Output::from_base_units(self.get_base_units() / rhs.get_base_units())
92+
}
93+
}
94+
}
95+
}
96+
97+
impl Measurement for std::time::Duration {
98+
fn get_base_units(&self) -> f64 {
99+
self.as_secs() as f64 + ((self.subsec_nanos() as f64) * 1e-9)
100+
}
101+
102+
fn from_base_units(units: f64) -> Self {
103+
let subsec_nanos = ((units * 1e9) % 1e9) as u32;
104+
let secs = units as u64;
105+
std::time::Duration::new(secs, subsec_nanos)
106+
}
107+
108+
fn get_base_units_name(&self) -> &'static str {
109+
"s"
110+
}
40111
}
41112

113+
impl_maths!(Area, Length);
114+
impl_maths!(Energy, Force, Length);
115+
impl_maths!(Energy, std::time::Duration, Power);
116+
impl_maths!(Force, Mass, Acceleration);
117+
impl_maths!(Force, Pressure, Area);
118+
impl_maths!(Length, std::time::Duration, Speed);
119+
impl_maths!(Power, Force, Speed);
120+
impl_maths!(Speed, std::time::Duration, Acceleration);
121+
impl_maths!(Volume, Length, Area);
122+
42123
// Include when running tests, but don't export them
43124
#[cfg(test)]
44125
#[allow(dead_code)]

src/mass.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use super::measurement::*;
2-
use super::*;
32

43
/// The `Mass` struct can be used to deal with mass in a common way.
54
///
@@ -146,15 +145,6 @@ impl Mass {
146145
}
147146
}
148147

149-
/// Mass * Acceleration = Force
150-
impl ::std::ops::Mul<Acceleration> for Mass {
151-
type Output = Force;
152-
153-
fn mul(self, rhs: Acceleration) -> Force {
154-
rhs * self
155-
}
156-
}
157-
158148
impl Measurement for Mass {
159149
fn get_base_units(&self) -> f64 {
160150
self.kilograms

src/power.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use super::measurement::*;
2-
use super::*;
3-
use std::time::Duration;
42

53
/// The `Power` struct can be used to deal with energies in a common way.
64
/// Common metric and imperial units are supported.
@@ -53,24 +51,6 @@ impl Power {
5351
}
5452
}
5553

56-
/// Power * Time = Energy
57-
impl ::std::ops::Mul<Duration> for Power {
58-
type Output = Energy;
59-
60-
fn mul(self, rhs: Duration) -> Energy {
61-
Energy::from_joules(self.as_watts() * duration_as_f64(rhs))
62-
}
63-
}
64-
65-
/// Time * Power = Energy
66-
impl ::std::ops::Mul<Power> for Duration {
67-
type Output = Energy;
68-
69-
fn mul(self, rhs: Power) -> Energy {
70-
rhs * self
71-
}
72-
}
73-
7454
impl Measurement for Power {
7555
fn get_base_units(&self) -> f64 {
7656
self.watts

0 commit comments

Comments
 (0)