|
1 | 1 | //! Types and constants for handling acceleration.
|
2 | 2 |
|
3 |
| -use super::measurement::*; |
4 | 3 | use super::length;
|
| 4 | +use super::measurement::*; |
| 5 | +#[cfg(feature = "from_str")] |
| 6 | +use regex::Regex; |
| 7 | +#[cfg(feature = "from_str")] |
| 8 | +use std::str::FromStr; |
5 | 9 |
|
6 | 10 | /// The `Acceleration` struct can be used to deal with Accelerations in a common way.
|
7 | 11 | /// Common metric and imperial units are supported.
|
@@ -78,14 +82,47 @@ impl Measurement for Acceleration {
|
78 | 82 | }
|
79 | 83 | }
|
80 | 84 |
|
| 85 | +#[cfg(feature = "from_str")] |
| 86 | +impl FromStr for Acceleration { |
| 87 | + type Err = std::num::ParseFloatError; |
| 88 | + |
| 89 | + /// Create a new Acceleration from a string |
| 90 | + /// Plain numbers in string are considered to be meters per second |
| 91 | + 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 | + |
81 | 118 | implement_measurement! { Acceleration }
|
82 | 119 |
|
83 | 120 | #[cfg(test)]
|
84 | 121 | mod test {
|
85 | 122 |
|
86 | 123 | use super::*;
|
87 |
| - use test_utils::assert_almost_eq; |
88 | 124 | use speed::Speed;
|
| 125 | + use test_utils::assert_almost_eq; |
89 | 126 |
|
90 | 127 | // Metric
|
91 | 128 | #[test]
|
@@ -158,4 +195,66 @@ mod test {
|
158 | 195 | assert_eq!(a > b, false);
|
159 | 196 | assert_eq!(a >= b, false);
|
160 | 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 | + } |
161 | 260 | }
|
0 commit comments