1
+ use crate :: ParseBoundsError :: { BadLen , ParseCoordError } ;
1
2
use serde_tuple:: { Deserialize_tuple , Serialize_tuple } ;
2
3
use std:: fmt:: { Display , Formatter } ;
3
4
use std:: num:: ParseFloatError ;
@@ -148,10 +149,48 @@ pub enum ParseBoundsError {
148
149
impl Display for ParseBoundsError {
149
150
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
150
151
match self {
151
- ParseBoundsError :: BadLen => {
152
- f. write_str ( "Incorrect number of values. Bounds expects four f64 values." )
153
- }
154
- ParseBoundsError :: ParseCoordError ( e) => e. fmt ( f) ,
152
+ BadLen => f. write_str ( "Incorrect number of values. Bounds expects four f64 values." ) ,
153
+ ParseCoordError ( e) => e. fmt ( f) ,
154
+ }
155
+ }
156
+ }
157
+
158
+ impl From < [ f64 ; 4 ] > for Bounds {
159
+ /// Parse four f64 values as a Bounds value, same order as the [Bounds::new] constructor.
160
+ ///
161
+ /// ```
162
+ /// # use tilejson::Bounds;
163
+ /// assert_eq!(
164
+ /// Bounds::new(1., 2., 3., 4.),
165
+ /// Bounds::from([1., 2., 3., 4.])
166
+ /// );
167
+ /// ```
168
+ fn from ( value : [ f64 ; 4 ] ) -> Self {
169
+ Self {
170
+ left : value[ 0 ] ,
171
+ bottom : value[ 1 ] ,
172
+ right : value[ 2 ] ,
173
+ top : value[ 3 ] ,
174
+ }
175
+ }
176
+ }
177
+
178
+ impl From < [ i32 ; 4 ] > for Bounds {
179
+ /// Parse four i32 values as a Bounds value, same order as the [Bounds::new] constructor.
180
+ ///
181
+ /// ```
182
+ /// # use tilejson::Bounds;
183
+ /// assert_eq!(
184
+ /// Bounds::new(1., 2., 3., 4.),
185
+ /// Bounds::from([1, 2, 3, 4])
186
+ /// );
187
+ /// ```
188
+ fn from ( value : [ i32 ; 4 ] ) -> Self {
189
+ Self {
190
+ left : value[ 0 ] as f64 ,
191
+ bottom : value[ 1 ] as f64 ,
192
+ right : value[ 2 ] as f64 ,
193
+ top : value[ 3 ] as f64 ,
155
194
}
156
195
}
157
196
}
@@ -160,17 +199,53 @@ impl TryFrom<Vec<f64>> for Bounds {
160
199
type Error = ParseBoundsError ;
161
200
162
201
/// Parse four f64 values as a Bounds value, same order as the [Bounds::new] constructor.
202
+ ///
203
+ /// ```
204
+ /// # use tilejson::Bounds;
205
+ /// assert_eq!(
206
+ /// Bounds::new(1., 2., 3., 4.),
207
+ /// Bounds::try_from(vec![1., 2., 3., 4.]).unwrap()
208
+ /// );
209
+ /// ```
163
210
fn try_from ( value : Vec < f64 > ) -> Result < Self , Self :: Error > {
164
- if value. len ( ) == 4 {
165
- Ok ( Self {
166
- left : value[ 0 ] ,
167
- bottom : value[ 1 ] ,
168
- right : value[ 2 ] ,
169
- top : value[ 3 ] ,
170
- } )
171
- } else {
172
- Err ( ParseBoundsError :: BadLen )
173
- }
211
+ let arr: [ f64 ; 4 ] = value. try_into ( ) . map_err ( |_| BadLen ) ?;
212
+ Ok ( arr. into ( ) )
213
+ }
214
+ }
215
+
216
+ impl TryFrom < & [ f64 ] > for Bounds {
217
+ type Error = ParseBoundsError ;
218
+
219
+ /// Parse four f64 values as a Bounds value, same order as the [Bounds::new] constructor.
220
+ ///
221
+ /// ```
222
+ /// # use tilejson::Bounds;
223
+ /// assert_eq!(
224
+ /// Bounds::new(1., 2., 3., 4.),
225
+ /// Bounds::try_from(vec![1., 2., 3., 4.].as_slice()).unwrap()
226
+ /// );
227
+ /// ```
228
+ fn try_from ( value : & [ f64 ] ) -> Result < Self , Self :: Error > {
229
+ let arr: [ f64 ; 4 ] = value. try_into ( ) . map_err ( |_| BadLen ) ?;
230
+ Ok ( arr. into ( ) )
231
+ }
232
+ }
233
+
234
+ impl TryFrom < & [ i32 ] > for Bounds {
235
+ type Error = ParseBoundsError ;
236
+
237
+ /// Parse four i32 values as a Bounds value, same order as the [Bounds::new] constructor.
238
+ ///
239
+ /// ```
240
+ /// # use tilejson::Bounds;
241
+ /// assert_eq!(
242
+ /// Bounds::new(1., 2., 3., 4.),
243
+ /// Bounds::try_from(vec![1, 2, 3, 4].as_slice()).unwrap()
244
+ /// );
245
+ /// ```
246
+ fn try_from ( value : & [ i32 ] ) -> Result < Self , Self :: Error > {
247
+ let arr: [ i32 ; 4 ] = value. try_into ( ) . map_err ( |_| BadLen ) ?;
248
+ Ok ( arr. into ( ) )
174
249
}
175
250
}
176
251
@@ -188,28 +263,26 @@ impl FromStr for Bounds {
188
263
/// assert_eq!(bounds, Bounds::new(-1.0, -2.0, 3.0, 4.0));
189
264
/// ```
190
265
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
191
- let mut vals = s. split ( ',' ) . map ( |s| s. trim ( ) ) ;
192
- let mut next_val = || {
193
- vals. next ( ) . map_or ( Err ( ParseBoundsError :: BadLen ) , |v| {
194
- v. parse ( ) . map_err ( ParseBoundsError :: ParseCoordError )
195
- } )
196
- } ;
197
- let bounds = Self {
198
- left : next_val ( ) ?,
199
- bottom : next_val ( ) ?,
200
- right : next_val ( ) ?,
201
- top : next_val ( ) ?,
202
- } ;
203
- match vals. next ( ) {
204
- Some ( _) => Err ( ParseBoundsError :: BadLen ) ,
205
- None => Ok ( bounds) ,
266
+ let mut values = s. split ( ',' ) ;
267
+ let mut result = [ 0. ; 4 ] ;
268
+ for i in 0 ..4 {
269
+ result[ i] = values
270
+ . next ( )
271
+ . ok_or ( ParseBoundsError :: BadLen ) ?
272
+ . trim ( )
273
+ . parse ( )
274
+ . map_err ( ParseBoundsError :: ParseCoordError ) ?;
206
275
}
276
+ values
277
+ . next ( )
278
+ . map_or ( Ok ( result. into ( ) ) , |_| Err ( ParseBoundsError :: BadLen ) )
207
279
}
208
280
}
209
281
210
282
#[ cfg( test) ]
211
283
mod tests {
212
284
use super :: * ;
285
+ use crate :: ParseBoundsError :: BadLen ;
213
286
214
287
#[ test]
215
288
fn test_parse_err ( ) {
@@ -232,4 +305,33 @@ mod tests {
232
305
assert_eq ! ( val( "0,0,0,0" ) , Bounds :: new( 0.0 , 0.0 , 0.0 , 0.0 ) ) ;
233
306
assert_eq ! ( val( " 1 ,2.0, 3.0, 4.0 " ) , Bounds :: new( 1.0 , 2.0 , 3.0 , 4.0 ) ) ;
234
307
}
308
+
309
+ #[ test]
310
+ fn test_parse_errors ( ) {
311
+ let err = |s| Bounds :: from_str ( s) . unwrap_err ( ) ;
312
+ assert_eq ! ( err( "0,0,0" ) , BadLen ) ;
313
+ assert_eq ! ( err( "0,0,0,0,0" ) , BadLen ) ;
314
+ assert ! ( matches!( err( "" ) , ParseCoordError ( _) ) ) ;
315
+ assert ! ( matches!( err( "a" ) , ParseCoordError ( _) ) ) ;
316
+ assert ! ( matches!( err( "0,0,0,1a" ) , ParseCoordError ( _) ) ) ;
317
+ }
318
+
319
+ #[ test]
320
+ fn test_from ( ) -> Result < ( ) , ParseBoundsError > {
321
+ let exp = Bounds :: new ( 1.0 , 2.0 , 3.0 , 4.0 ) ;
322
+ assert_eq ! ( exp, Bounds :: from( [ 1.0 , 2.0 , 3.0 , 4.0 ] ) ) ;
323
+ assert_eq ! ( exp, Bounds :: try_from( [ 1.0 , 2.0 , 3.0 , 4.0 ] . as_slice( ) ) ?) ;
324
+ assert_eq ! ( exp, Bounds :: try_from( vec![ 1.0 , 2.0 , 3.0 , 4.0 ] ) ?) ;
325
+ let val = vec ! [ 1.0 , 2.0 , 3.0 , 4.0 ] ;
326
+ assert_eq ! ( exp, Bounds :: try_from( ( & val) . as_slice( ) ) ?) ;
327
+ assert_eq ! ( exp, Bounds :: try_from( val. as_slice( ) ) ?) ;
328
+
329
+ // i32
330
+ assert_eq ! ( exp, Bounds :: from( [ 1 , 2 , 3 , 4 ] ) ) ;
331
+ assert_eq ! ( exp, Bounds :: try_from( [ 1 , 2 , 3 , 4 ] . as_slice( ) ) ?) ;
332
+ let val = vec ! [ 1 , 2 , 3 , 4 ] ;
333
+ assert_eq ! ( exp, Bounds :: try_from( ( & val) . as_slice( ) ) ?) ;
334
+ assert_eq ! ( exp, Bounds :: try_from( val. as_slice( ) ) ?) ;
335
+ Ok ( ( ) )
336
+ }
235
337
}
0 commit comments