measurements/
acceleration.rs1use super::length;
4use super::measurement::*;
5#[cfg(feature = "from_str")]
6use regex::Regex;
7#[cfg(feature = "from_str")]
8use std::str::FromStr;
9
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30#[derive(Copy, Clone, Debug)]
31pub struct Acceleration {
32 meters_per_second_per_second: f64,
33}
34
35impl Acceleration {
36 pub fn from_meters_per_second_per_second(meters_per_second_per_second: f64) -> Acceleration {
38 Acceleration {
39 meters_per_second_per_second,
40 }
41 }
42
43 pub fn from_metres_per_second_per_second(metres_per_second_per_second: f64) -> Acceleration {
45 Acceleration::from_meters_per_second_per_second(metres_per_second_per_second)
46 }
47
48 pub fn from_feet_per_second_per_second(feet_per_second_per_second: f64) -> Acceleration {
50 Acceleration::from_metres_per_second_per_second(
51 feet_per_second_per_second / length::METER_FEET_FACTOR,
52 )
53 }
54
55 pub fn as_meters_per_second_per_second(&self) -> f64 {
57 self.meters_per_second_per_second
58 }
59
60 pub fn as_metres_per_second_per_second(&self) -> f64 {
62 self.as_meters_per_second_per_second()
63 }
64
65 pub fn as_feet_per_second_per_second(&self) -> f64 {
67 self.meters_per_second_per_second * length::METER_FEET_FACTOR
68 }
69}
70
71impl Measurement for Acceleration {
72 fn as_base_units(&self) -> f64 {
73 self.meters_per_second_per_second
74 }
75
76 fn from_base_units(units: f64) -> Self {
77 Self::from_meters_per_second_per_second(units)
78 }
79
80 fn get_base_units_name(&self) -> &'static str {
81 "m/s\u{00B2}"
82 }
83}
84
85#[cfg(feature = "from_str")]
86impl FromStr for Acceleration {
87 type Err = std::num::ParseFloatError;
88
89 fn from_str(val: &str) -> Result<Self, Self::Err> {
92 if val.is_empty() {
93 return Ok(Acceleration::from_metres_per_second_per_second(0.0));
94 }
95
96 let re = Regex::new(r"(?i)\s*([0-9.]*)\s?([ftmps -1]{1,6})\s*$").unwrap();
97 if let Some(caps) = re.captures(val) {
98 let float_val = caps.get(1).unwrap().as_str();
99 return Ok(
100 match caps.get(2).unwrap().as_str().to_lowercase().as_str() {
101 "m/s" | "m s-1" => {
102 Acceleration::from_meters_per_second_per_second(float_val.parse::<f64>()?)
103 }
104 "ft/s" | "fps" | "ft s-1" => {
105 Acceleration::from_feet_per_second_per_second(float_val.parse::<f64>()?)
106 }
107 _ => Acceleration::from_meters_per_second_per_second(val.parse::<f64>()?),
108 },
109 );
110 }
111
112 Ok(Acceleration::from_meters_per_second_per_second(
113 val.parse::<f64>()?,
114 ))
115 }
116}
117
118implement_measurement! { Acceleration }
119
120#[cfg(test)]
121mod test {
122
123 use super::*;
124 use speed::Speed;
125 use test_utils::assert_almost_eq;
126
127 #[test]
129 fn speed_over_time() {
130 let s1 = Speed::from_meters_per_second(10.0);
131 let t1 = ::time::Duration::new(5, 0);
132 let i1 = s1 / t1;
133 let r1 = i1.as_meters_per_second_per_second();
134 assert_almost_eq(r1, 2.0);
135 }
136
137 #[test]
139 fn add() {
140 let a = Acceleration::from_meters_per_second_per_second(2.0);
141 let b = Acceleration::from_meters_per_second_per_second(4.0);
142 let c = a + b;
143 let d = b + a;
144 assert_almost_eq(c.as_meters_per_second_per_second(), 6.0);
145 assert_eq!(c, d);
146 }
147
148 #[test]
149 fn sub() {
150 let a = Acceleration::from_meters_per_second_per_second(2.0);
151 let b = Acceleration::from_meters_per_second_per_second(4.0);
152 let c = a - b;
153 assert_almost_eq(c.as_meters_per_second_per_second(), -2.0);
154 }
155
156 #[test]
157 fn mul() {
158 let a = Acceleration::from_meters_per_second_per_second(3.0);
159 let b = a * 2.0;
160 let c = 2.0 * a;
161 assert_almost_eq(b.as_meters_per_second_per_second(), 6.0);
162 assert_eq!(b, c);
163 }
164
165 #[test]
166 fn div() {
167 let a = Acceleration::from_meters_per_second_per_second(2.0);
168 let b = Acceleration::from_meters_per_second_per_second(4.0);
169 let c = a / b;
170 let d = a / 2.0;
171 assert_almost_eq(c, 0.5);
172 assert_almost_eq(d.as_meters_per_second_per_second(), 1.0);
173 }
174
175 #[test]
176 fn eq() {
177 let a = Acceleration::from_meters_per_second_per_second(2.0);
178 let b = Acceleration::from_meters_per_second_per_second(2.0);
179 assert_eq!(a == b, true);
180 }
181
182 #[test]
183 fn neq() {
184 let a = Acceleration::from_meters_per_second_per_second(2.0);
185 let b = Acceleration::from_meters_per_second_per_second(4.0);
186 assert_eq!(a == b, false);
187 }
188
189 #[test]
190 fn cmp() {
191 let a = Acceleration::from_meters_per_second_per_second(2.0);
192 let b = Acceleration::from_meters_per_second_per_second(4.0);
193 assert_eq!(a < b, true);
194 assert_eq!(a <= b, true);
195 assert_eq!(a > b, false);
196 assert_eq!(a >= b, false);
197 }
198
199 #[test]
200 #[cfg(feature = "from_str")]
201 fn meters_per_second_str() {
202 let t = Acceleration::from_str(" 12.0m/s");
203 assert!(t.is_ok());
204 let o = t.unwrap().as_meters_per_second_per_second();
205 assert_almost_eq(12.0, o);
206 }
207
208 #[test]
209 #[cfg(feature = "from_str")]
210 fn meters_per_second_minus_str() {
211 let t = Acceleration::from_str("12.0 m s-1");
212 assert!(t.is_ok());
213 let o = t.unwrap().as_meters_per_second_per_second();
214 assert_almost_eq(12.0, o);
215 }
216
217 #[test]
218 #[cfg(feature = "from_str")]
219 fn feet_per_second_str() {
220 let t = Acceleration::from_str(" 12.0ft/s");
221 assert!(t.is_ok());
222 let o = t.unwrap().as_feet_per_second_per_second();
223 assert_almost_eq(12.0, o);
224 }
225
226 #[test]
227 #[cfg(feature = "from_str")]
228 fn feet_per_second_fps_str() {
229 let t = Acceleration::from_str(" 12.0fps");
230 assert!(t.is_ok());
231 let o = t.unwrap().as_feet_per_second_per_second();
232 assert_almost_eq(12.0, o);
233 }
234
235 #[test]
236 #[cfg(feature = "from_str")]
237 fn feet_per_second_minus_str() {
238 let t = Acceleration::from_str("12.0 ft s-1");
239 assert!(t.is_ok());
240 let o = t.unwrap().as_feet_per_second_per_second();
241 assert_almost_eq(12.0, o);
242 }
243
244 #[test]
245 #[cfg(feature = "from_str")]
246 fn number_str() {
247 let t = Acceleration::from_str("100.5");
248 assert!(t.is_ok());
249
250 let o = t.unwrap().as_meters_per_second_per_second();
251 assert_almost_eq(o, 100.5);
252 }
253
254 #[test]
255 #[cfg(feature = "from_str")]
256 fn invalid_str() {
257 let t = Acceleration::from_str("abcd");
258 assert!(t.is_err());
259 }
260}