-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathunits.rs
139 lines (128 loc) · 4.33 KB
/
units.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Module to allow the use of serde with uom quantities
//!
//! The serde feature of uom doesn’t allow to specify in which unit the value will be serialized.
//!
//! Two helpers are provided for convenience:
//! * `unit::new` (e.g. `meter::new(32)`) to build a new quantity form a f64 in the given unit
//! * `unit::from` (e.g. `millimeter::from(length)`) to have the quantity as f64 in the given unit
//!
//! ## Usage
//!
//! ```ignore
//! use editoast_model::units::*;
//! #[derive(Debug, Serialize, Derivative)]
//! struct Train {
//! // This means that serde with read and write the velocity in meters per second
//! #[serde(with="meter_per_second")]
//! max_speed: Velocity,
//! // When using optional values, we must add `default` and use ::option unit
//! // See https://stackoverflow.com/a/44303505
//! #[serde(default, with="meter::option")]
//! length: Option<Length>,
//! }
//!
//! impl Train {
//! fn from_meter_per_seconds(mps: f64) -> Self {
//! Self {
//! max_speed: meter_per_second::new(f64),
//! }
//! }
//!
//! fn print(&self) {
//! println!("The max speed is: {} km/h", kilometer_per_hour::from(self.max_speed));
//! }
//! }
//! ```
/// Re-export the Quantities that are used in OSRD
pub use uom::si::f64::{
Acceleration, Force, Frequency, Length, LinearMassDensity, LinearNumberDensity, Mass, MassRate,
Velocity,
};
macro_rules! quantity_to_path {
(Length, $unit:ident) => {
uom::si::length::$unit
};
(Velocity, $unit:ident) => {
uom::si::velocity::$unit
};
(Acceleration, $unit:ident) => {
uom::si::acceleration::$unit
};
(Mass, $unit:ident) => {
uom::si::mass::$unit
};
(Force, $unit:ident) => {
uom::si::force::$unit
};
(MassRate, $unit:ident) => {
uom::si::mass_rate::$unit
};
(Frequency, $unit:ident) => {
uom::si::frequency::$unit
};
(LinearMassDensity, $unit:ident) => {
uom::si::linear_mass_density::$unit
};
(LinearNumberDensity, $unit:ident) => {
uom::si::linear_number_density::$unit
};
}
macro_rules! define_unit {
($unit:ident, $quantity:ident) => {
pub mod $unit {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use uom::si::f64::*;
type Unit = quantity_to_path!($quantity, $unit);
pub fn serialize<S>(value: &$quantity, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
value.get::<Unit>().serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<$quantity, D::Error>
where
D: Deserializer<'de>,
{
let value = f64::deserialize(deserializer)?;
Ok($quantity::new::<Unit>(value))
}
pub fn new(value: f64) -> $quantity {
$quantity::new::<Unit>(value)
}
pub fn from(qty: &$quantity) -> f64 {
qty.get::<Unit>()
}
pub mod option {
use super::*;
pub fn serialize<S>(
value: &Option<$quantity>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
value.map(|value| value.get::<Unit>()).serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<$quantity>, D::Error>
where
D: Deserializer<'de>,
{
let value = Option::deserialize(deserializer)?;
Ok(value.map(|value| $quantity::new::<Unit>(value)))
}
}
}
};
}
// Any new value here must also be added in editoast_derive/src/annotate_units.rs
define_unit!(meter, Length);
define_unit!(millimeter, Length);
define_unit!(meter_per_second, Velocity);
define_unit!(kilometer_per_hour, Velocity);
define_unit!(meter_per_second_squared, Acceleration);
define_unit!(kilogram, Mass);
define_unit!(newton, Force);
define_unit!(kilogram_per_second, MassRate);
define_unit!(hertz, Frequency);
define_unit!(kilogram_per_meter, LinearMassDensity);
define_unit!(per_meter, LinearNumberDensity);