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,68 @@ 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 < [ f32 ; 4 ] > for Bounds {
179
+ /// Parse four f32 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.0f32, 2.0f32, 3.0f32, 4.0f32])
186
+ /// );
187
+ /// ```
188
+ fn from ( value : [ f32 ; 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 ,
194
+ }
195
+ }
196
+ }
197
+
198
+ impl From < [ i32 ; 4 ] > for Bounds {
199
+ /// Parse four i32 values as a Bounds value, same order as the [Bounds::new] constructor.
200
+ ///
201
+ /// ```
202
+ /// # use tilejson::Bounds;
203
+ /// assert_eq!(
204
+ /// Bounds::new(1., 2., 3., 4.),
205
+ /// Bounds::from([1, 2, 3, 4])
206
+ /// );
207
+ /// ```
208
+ fn from ( value : [ i32 ; 4 ] ) -> Self {
209
+ Self {
210
+ left : value[ 0 ] as f64 ,
211
+ bottom : value[ 1 ] as f64 ,
212
+ right : value[ 2 ] as f64 ,
213
+ top : value[ 3 ] as f64 ,
155
214
}
156
215
}
157
216
}
@@ -160,17 +219,71 @@ impl TryFrom<Vec<f64>> for Bounds {
160
219
type Error = ParseBoundsError ;
161
220
162
221
/// Parse four f64 values as a Bounds value, same order as the [Bounds::new] constructor.
222
+ ///
223
+ /// ```
224
+ /// # use tilejson::Bounds;
225
+ /// assert_eq!(
226
+ /// Bounds::new(1., 2., 3., 4.),
227
+ /// Bounds::try_from(vec![1., 2., 3., 4.]).unwrap()
228
+ /// );
229
+ /// ```
163
230
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
- }
231
+ let arr: [ f64 ; 4 ] = value. try_into ( ) . map_err ( |_| BadLen ) ?;
232
+ Ok ( arr. into ( ) )
233
+ }
234
+ }
235
+
236
+ impl TryFrom < & [ f64 ] > for Bounds {
237
+ type Error = ParseBoundsError ;
238
+
239
+ /// Parse four f64 values as a Bounds value, same order as the [Bounds::new] constructor.
240
+ ///
241
+ /// ```
242
+ /// # use tilejson::Bounds;
243
+ /// assert_eq!(
244
+ /// Bounds::new(1., 2., 3., 4.),
245
+ /// Bounds::try_from(vec![1., 2., 3., 4.].as_slice()).unwrap()
246
+ /// );
247
+ /// ```
248
+ fn try_from ( value : & [ f64 ] ) -> Result < Self , Self :: Error > {
249
+ let arr: [ f64 ; 4 ] = value. try_into ( ) . map_err ( |_| BadLen ) ?;
250
+ Ok ( arr. into ( ) )
251
+ }
252
+ }
253
+
254
+ impl TryFrom < & [ f32 ] > for Bounds {
255
+ type Error = ParseBoundsError ;
256
+
257
+ /// Parse four f32 values as a Bounds value, same order as the [Bounds::new] constructor.
258
+ ///
259
+ /// ```
260
+ /// # use tilejson::Bounds;
261
+ /// assert_eq!(
262
+ /// Bounds::new(1., 2., 3., 4.),
263
+ /// Bounds::try_from(vec![1.0f32, 2.0f32, 3.0f32, 4.0f32].as_slice()).unwrap()
264
+ /// );
265
+ /// ```
266
+ fn try_from ( value : & [ f32 ] ) -> Result < Self , Self :: Error > {
267
+ let arr: [ f32 ; 4 ] = value. try_into ( ) . map_err ( |_| BadLen ) ?;
268
+ Ok ( arr. into ( ) )
269
+ }
270
+ }
271
+
272
+ impl TryFrom < & [ i32 ] > for Bounds {
273
+ type Error = ParseBoundsError ;
274
+
275
+ /// Parse four i32 values as a Bounds value, same order as the [Bounds::new] constructor.
276
+ ///
277
+ /// ```
278
+ /// # use tilejson::Bounds;
279
+ /// assert_eq!(
280
+ /// Bounds::new(1., 2., 3., 4.),
281
+ /// Bounds::try_from(vec![1, 2, 3, 4].as_slice()).unwrap()
282
+ /// );
283
+ /// ```
284
+ fn try_from ( value : & [ i32 ] ) -> Result < Self , Self :: Error > {
285
+ let arr: [ i32 ; 4 ] = value. try_into ( ) . map_err ( |_| BadLen ) ?;
286
+ Ok ( arr. into ( ) )
174
287
}
175
288
}
176
289
@@ -188,28 +301,26 @@ impl FromStr for Bounds {
188
301
/// assert_eq!(bounds, Bounds::new(-1.0, -2.0, 3.0, 4.0));
189
302
/// ```
190
303
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) ,
304
+ let mut values = s. split ( ',' ) ;
305
+ let mut result = [ 0. ; 4 ] ;
306
+ for i in 0 ..4 {
307
+ result[ i] = values
308
+ . next ( )
309
+ . ok_or ( ParseBoundsError :: BadLen ) ?
310
+ . trim ( )
311
+ . parse ( )
312
+ . map_err ( ParseBoundsError :: ParseCoordError ) ?;
206
313
}
314
+ values
315
+ . next ( )
316
+ . map_or ( Ok ( result. into ( ) ) , |_| Err ( ParseBoundsError :: BadLen ) )
207
317
}
208
318
}
209
319
210
320
#[ cfg( test) ]
211
321
mod tests {
212
322
use super :: * ;
323
+ use crate :: ParseBoundsError :: BadLen ;
213
324
214
325
#[ test]
215
326
fn test_parse_err ( ) {
@@ -232,4 +343,41 @@ mod tests {
232
343
assert_eq ! ( val( "0,0,0,0" ) , Bounds :: new( 0.0 , 0.0 , 0.0 , 0.0 ) ) ;
233
344
assert_eq ! ( val( " 1 ,2.0, 3.0, 4.0 " ) , Bounds :: new( 1.0 , 2.0 , 3.0 , 4.0 ) ) ;
234
345
}
346
+
347
+ #[ test]
348
+ fn test_parse_errors ( ) {
349
+ let err = |s| Bounds :: from_str ( s) . unwrap_err ( ) ;
350
+ assert_eq ! ( err( "0,0,0" ) , BadLen ) ;
351
+ assert_eq ! ( err( "0,0,0,0,0" ) , BadLen ) ;
352
+ assert ! ( matches!( err( "" ) , ParseCoordError ( _) ) ) ;
353
+ assert ! ( matches!( err( "a" ) , ParseCoordError ( _) ) ) ;
354
+ assert ! ( matches!( err( "0,0,0,1a" ) , ParseCoordError ( _) ) ) ;
355
+ }
356
+
357
+ #[ test]
358
+ fn test_from ( ) -> Result < ( ) , ParseBoundsError > {
359
+ let exp = Bounds :: new ( 1.0 , 2.0 , 3.0 , 4.0 ) ;
360
+ assert_eq ! ( exp, Bounds :: from( [ 1.0 , 2.0 , 3.0 , 4.0 ] ) ) ;
361
+ assert_eq ! ( exp, Bounds :: try_from( [ 1.0 , 2.0 , 3.0 , 4.0 ] . as_slice( ) ) ?) ;
362
+ assert_eq ! ( exp, Bounds :: try_from( vec![ 1.0 , 2.0 , 3.0 , 4.0 ] ) ?) ;
363
+ let val = vec ! [ 1.0 , 2.0 , 3.0 , 4.0 ] ;
364
+ assert_eq ! ( exp, Bounds :: try_from( ( & val) . as_slice( ) ) ?) ;
365
+ assert_eq ! ( exp, Bounds :: try_from( val. as_slice( ) ) ?) ;
366
+
367
+ // f32
368
+ assert_eq ! ( exp, Bounds :: from( [ 1.0f32 , 2.0f32 , 3.0f32 , 4.0f32 ] ) ) ;
369
+ let val_array = [ 1.0f32 , 2.0f32 , 3.0f32 , 4.0f32 ] ;
370
+ assert_eq ! ( exp, Bounds :: try_from( val_array. as_slice( ) ) ?) ;
371
+ let val = vec ! [ 1.0f32 , 2.0f32 , 3.0f32 , 4.0f32 ] ;
372
+ assert_eq ! ( exp, Bounds :: try_from( ( & val) . as_slice( ) ) ?) ;
373
+ assert_eq ! ( exp, Bounds :: try_from( val. as_slice( ) ) ?) ;
374
+
375
+ // i32
376
+ assert_eq ! ( exp, Bounds :: from( [ 1 , 2 , 3 , 4 ] ) ) ;
377
+ assert_eq ! ( exp, Bounds :: try_from( [ 1 , 2 , 3 , 4 ] . as_slice( ) ) ?) ;
378
+ let val = vec ! [ 1 , 2 , 3 , 4 ] ;
379
+ assert_eq ! ( exp, Bounds :: try_from( ( & val) . as_slice( ) ) ?) ;
380
+ assert_eq ! ( exp, Bounds :: try_from( val. as_slice( ) ) ?) ;
381
+ Ok ( ( ) )
382
+ }
235
383
}
0 commit comments