Skip to content

Commit 529098e

Browse files
drodileldruin
authored andcommitted
Add support to create Angle from string
Again behind the from_str feature. Tests included.
1 parent f4918b6 commit 529098e

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

src/angle.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
33
use super::measurement::*;
44

5+
#[cfg(feature = "from_str")]
6+
use regex::Regex;
7+
#[cfg(feature = "from_str")]
8+
use std::str::FromStr;
9+
510
/// The 'Angle' struct can be used to deal with angles in a common way.
611
///
712
/// # Example
@@ -98,6 +103,33 @@ impl Measurement for Angle {
98103
}
99104
}
100105

106+
#[cfg(feature = "from_str")]
107+
impl FromStr for Angle {
108+
type Err = std::num::ParseFloatError;
109+
110+
/// Create a new Angle from a string
111+
/// Plain numbers in string are considered to be plain degrees
112+
fn from_str(val: &str) -> Result<Self, Self::Err> {
113+
if val.is_empty() {
114+
return Ok(Angle::from_degrees(0.0));
115+
}
116+
117+
let re = Regex::new(r"(?i)\s*([0-9.]*)\s?(deg|\u{00B0}|rad)\s*$").unwrap();
118+
if let Some(caps) = re.captures(val) {
119+
let float_val = caps.get(1).unwrap().as_str();
120+
return Ok(
121+
match caps.get(2).unwrap().as_str().to_lowercase().as_str() {
122+
"deg" | "\u{00B0}" => Angle::from_degrees(float_val.parse::<f64>()?),
123+
"rad" => Angle::from_radians(float_val.parse::<f64>()?),
124+
_ => Angle::from_degrees(val.parse::<f64>()?),
125+
},
126+
);
127+
}
128+
129+
Ok(Angle::from_degrees(val.parse::<f64>()?))
130+
}
131+
}
132+
101133
implement_measurement! { Angle }
102134

103135
#[cfg(test)]
@@ -115,4 +147,51 @@ mod test {
115147
assert_almost_eq(r1, 2.0 * PI);
116148
assert_almost_eq(r2, 180.0);
117149
}
150+
151+
#[test]
152+
#[cfg(feature = "from_str")]
153+
fn angle_from_str() {
154+
let t = Angle::from_str("100 deg");
155+
assert!(t.is_ok());
156+
157+
let o = t.unwrap().as_degrees();
158+
assert_almost_eq(o, 100.0);
159+
}
160+
161+
#[test]
162+
#[cfg(feature = "from_str")]
163+
fn angle_from_degree_str() {
164+
let t = Angle::from_str("100°");
165+
assert!(t.is_ok());
166+
167+
let o = t.unwrap().as_degrees();
168+
assert_almost_eq(o, 100.0);
169+
}
170+
171+
#[test]
172+
#[cfg(feature = "from_str")]
173+
fn angle_from_radian_str() {
174+
let t = Angle::from_str("100rad");
175+
assert!(t.is_ok());
176+
177+
let o = t.unwrap().as_radians();
178+
assert_almost_eq(o, 100.0);
179+
}
180+
181+
#[test]
182+
#[cfg(feature = "from_str")]
183+
fn default_str() {
184+
let t = Angle::from_str("100");
185+
assert!(t.is_ok());
186+
187+
let o = t.unwrap().as_degrees();
188+
assert_almost_eq(o, 100.0);
189+
}
190+
191+
#[test]
192+
#[cfg(feature = "from_str")]
193+
fn invalid_str() {
194+
let t = Angle::from_str("abcd");
195+
assert!(t.is_err());
196+
}
118197
}

0 commit comments

Comments
 (0)