2
2
3
3
use super :: measurement:: * ;
4
4
5
+ #[ cfg( feature = "from_str" ) ]
6
+ use regex:: Regex ;
7
+ #[ cfg( feature = "from_str" ) ]
8
+ use std:: str:: FromStr ;
9
+
5
10
/// The 'Angle' struct can be used to deal with angles in a common way.
6
11
///
7
12
/// # Example
@@ -98,6 +103,33 @@ impl Measurement for Angle {
98
103
}
99
104
}
100
105
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
+
101
133
implement_measurement ! { Angle }
102
134
103
135
#[ cfg( test) ]
@@ -115,4 +147,51 @@ mod test {
115
147
assert_almost_eq ( r1, 2.0 * PI ) ;
116
148
assert_almost_eq ( r2, 180.0 ) ;
117
149
}
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
+ }
118
197
}
0 commit comments