@@ -232,7 +232,8 @@ impl BaseCode {
232
232
server_ip : & IpAddress ,
233
233
directory_name : & CStr8 ,
234
234
buffer : & ' a mut [ u8 ] ,
235
- ) -> Result < impl Iterator < Item = TftpFileInfo < ' a > > + ' a > {
235
+ ) -> Result < impl Iterator < Item = core:: result:: Result < TftpFileInfo < ' a > , ReadDirParseError > > + ' a >
236
+ {
236
237
let filename = NonNull :: from ( & directory_name. to_bytes_with_nul ( ) [ 0 ] ) . cast ( ) ;
237
238
238
239
let buffer_ptr = NonNull :: from ( & buffer[ 0 ] ) . cast ( ) ;
@@ -258,52 +259,37 @@ impl BaseCode {
258
259
let buffer = & buffer[ ..buffer_size] ;
259
260
260
261
let mut iterator = buffer. split_inclusive ( |b| * b == 0 ) ;
261
-
262
- Ok ( from_fn ( move || {
263
- let filename = iterator
264
- . next ( )
265
- . expect ( "the final entry should have an empty file name" ) ;
262
+ let mut parse_next = move || {
263
+ let filename = iterator. next ( ) . ok_or ( ReadDirParseError ) ?;
266
264
if filename == [ 0 ] {
267
265
// This is the final entry.
268
- return None ;
266
+ return Ok ( None ) ;
269
267
}
270
268
let filename = CStr8 :: from_bytes_with_nul ( filename) . unwrap ( ) ;
271
269
272
- let information_string = iterator
273
- . next ( )
274
- . expect ( "each file should have an information string" ) ;
270
+ let information_string = iterator. next ( ) . ok_or ( ReadDirParseError ) ?;
275
271
let ( _null_terminator, information_string) = information_string. split_last ( ) . unwrap ( ) ;
276
- let information_string = core :: str :: from_utf8 ( information_string )
277
- . expect ( "the information string should be valid utf-8" ) ;
272
+ let information_string =
273
+ core :: str :: from_utf8 ( information_string ) . map_err ( |_| ReadDirParseError ) ? ;
278
274
279
275
let ( size, rest) = information_string
280
276
. split_once ( ' ' )
281
- . expect ( "the information string should be valid" ) ;
282
- let ( year, rest) = rest
283
- . split_once ( '-' )
284
- . expect ( "the information string should be valid" ) ;
285
- let ( month, rest) = rest
286
- . split_once ( '-' )
287
- . expect ( "the information string should be valid" ) ;
288
- let ( day, rest) = rest
289
- . split_once ( ' ' )
290
- . expect ( "the information string should be valid" ) ;
291
- let ( hour, rest) = rest
292
- . split_once ( ':' )
293
- . expect ( "the information string should be valid" ) ;
294
- let ( minute, second) = rest
295
- . split_once ( ':' )
296
- . expect ( "the information string should be valid" ) ;
297
-
298
- let size = size. parse ( ) . expect ( "size should be a number" ) ;
299
- let year = year. parse ( ) . expect ( "year should be a number" ) ;
300
- let month = month. parse ( ) . expect ( "month should be a number" ) ;
301
- let day = day. parse ( ) . expect ( "day should be a number" ) ;
302
- let hour = hour. parse ( ) . expect ( "hour should be a number" ) ;
303
- let minute = minute. parse ( ) . expect ( "minute should be a number" ) ;
304
- let second = second. parse ( ) . expect ( "second should be a number" ) ;
305
-
306
- Some ( TftpFileInfo {
277
+ . ok_or ( ReadDirParseError ) ?;
278
+ let ( year, rest) = rest. split_once ( '-' ) . ok_or ( ReadDirParseError ) ?;
279
+ let ( month, rest) = rest. split_once ( '-' ) . ok_or ( ReadDirParseError ) ?;
280
+ let ( day, rest) = rest. split_once ( ' ' ) . ok_or ( ReadDirParseError ) ?;
281
+ let ( hour, rest) = rest. split_once ( ':' ) . ok_or ( ReadDirParseError ) ?;
282
+ let ( minute, second) = rest. split_once ( ':' ) . ok_or ( ReadDirParseError ) ?;
283
+
284
+ let size = size. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
285
+ let year = year. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
286
+ let month = month. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
287
+ let day = day. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
288
+ let hour = hour. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
289
+ let minute = minute. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
290
+ let second = second. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
291
+
292
+ Ok ( Some ( TftpFileInfo {
307
293
filename,
308
294
size,
309
295
year,
@@ -312,9 +298,9 @@ impl BaseCode {
312
298
hour,
313
299
minute,
314
300
second,
315
- } )
316
- } )
317
- . fuse ( ) )
301
+ } ) )
302
+ } ;
303
+ Ok ( from_fn ( move || parse_next ( ) . transpose ( ) ) . fuse ( ) )
318
304
}
319
305
320
306
/// Returns the size of a file located on a MTFTP server.
@@ -389,7 +375,8 @@ impl BaseCode {
389
375
server_ip : & IpAddress ,
390
376
buffer : & ' a mut [ u8 ] ,
391
377
info : & MtftpInfo ,
392
- ) -> Result < impl Iterator < Item = MtftpFileInfo < ' a > > + ' a > {
378
+ ) -> Result < impl Iterator < Item = core:: result:: Result < MtftpFileInfo < ' a > , ReadDirParseError > > + ' a >
379
+ {
393
380
let buffer_ptr = NonNull :: from ( & buffer[ 0 ] ) . cast ( ) ;
394
381
let mut buffer_size = u64:: try_from ( buffer. len ( ) ) . expect ( "buffer length should fit in u64" ) ;
395
382
@@ -413,71 +400,53 @@ impl BaseCode {
413
400
let buffer = & buffer[ ..buffer_size] ;
414
401
415
402
let mut iterator = buffer. split_inclusive ( |b| * b == 0 ) ;
416
-
417
- Ok ( from_fn ( move || {
418
- let filename = iterator
419
- . next ( )
420
- . expect ( "the final entry should have an empty file name" ) ;
403
+ let mut parse_next = move || {
404
+ let filename = iterator. next ( ) . ok_or ( ReadDirParseError ) ?;
421
405
if filename == [ 0 ] {
422
406
// This is the final entry.
423
- return None ;
407
+ return Ok ( None ) ;
424
408
}
425
409
let filename = CStr8 :: from_bytes_with_nul ( filename) . unwrap ( ) ;
426
410
427
- let multicast_ip = iterator
428
- . next ( )
429
- . expect ( "each file should have a multicast ip address" ) ;
411
+ let multicast_ip = iterator. next ( ) . ok_or ( ReadDirParseError ) ?;
430
412
let ( _null_terminator, multicast_ip) = multicast_ip. split_last ( ) . unwrap ( ) ;
431
- let multicast_ip = core:: str:: from_utf8 ( multicast_ip)
432
- . expect ( "the multicast ip address should be valid utf-8" ) ;
413
+ let multicast_ip = core:: str:: from_utf8 ( multicast_ip) . map_err ( |_| ReadDirParseError ) ?;
433
414
let mut octets = multicast_ip. split ( '.' ) ;
434
415
let mut buffer = [ 0 ; 4 ] ;
435
416
for b in buffer. iter_mut ( ) {
436
- let octet = octets
437
- . next ( )
438
- . expect ( "the information string should be valid" ) ;
439
- let octet = octet
440
- . parse ( )
441
- . expect ( "each octet in the ip address should be a number" ) ;
417
+ let octet = octets. next ( ) . ok_or ( ReadDirParseError ) ?;
418
+ let octet = octet. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
442
419
* b = octet;
443
420
}
421
+ if octets. next ( ) . is_some ( ) {
422
+ // The ip should have exact 4 octets, not more.
423
+ return Err ( ReadDirParseError ) ;
424
+ }
444
425
let ip_address = IpAddress :: new_v4 ( buffer) ;
445
426
446
- let information_string = iterator
447
- . next ( )
448
- . expect ( "each file should have an information string" ) ;
427
+ let information_string = iterator. next ( ) . ok_or ( ReadDirParseError ) ?;
449
428
let ( _null_terminator, information_string) = information_string. split_last ( ) . unwrap ( ) ;
450
- let information_string = core :: str :: from_utf8 ( information_string )
451
- . expect ( "the information string should be valid utf-8" ) ;
429
+ let information_string =
430
+ core :: str :: from_utf8 ( information_string ) . map_err ( |_| ReadDirParseError ) ? ;
452
431
453
432
let ( size, rest) = information_string
454
433
. split_once ( ' ' )
455
- . expect ( "the information string should be valid" ) ;
456
- let ( year, rest) = rest
457
- . split_once ( '-' )
458
- . expect ( "the information string should be valid" ) ;
459
- let ( month, rest) = rest
460
- . split_once ( '-' )
461
- . expect ( "the information string should be valid" ) ;
462
- let ( day, rest) = rest
463
- . split_once ( ' ' )
464
- . expect ( "the information string should be valid" ) ;
465
- let ( hour, rest) = rest
466
- . split_once ( ':' )
467
- . expect ( "the information string should be valid" ) ;
468
- let ( minute, second) = rest
469
- . split_once ( ':' )
470
- . expect ( "the information string should be valid" ) ;
471
-
472
- let size = size. parse ( ) . expect ( "size should be a number" ) ;
473
- let year = year. parse ( ) . expect ( "year should be a number" ) ;
474
- let month = month. parse ( ) . expect ( "month should be a number" ) ;
475
- let day = day. parse ( ) . expect ( "day should be a number" ) ;
476
- let hour = hour. parse ( ) . expect ( "hour should be a number" ) ;
477
- let minute = minute. parse ( ) . expect ( "minute should be a number" ) ;
478
- let second = second. parse ( ) . expect ( "second should be a number" ) ;
479
-
480
- Some ( MtftpFileInfo {
434
+ . ok_or ( ReadDirParseError ) ?;
435
+ let ( year, rest) = rest. split_once ( '-' ) . ok_or ( ReadDirParseError ) ?;
436
+ let ( month, rest) = rest. split_once ( '-' ) . ok_or ( ReadDirParseError ) ?;
437
+ let ( day, rest) = rest. split_once ( ' ' ) . ok_or ( ReadDirParseError ) ?;
438
+ let ( hour, rest) = rest. split_once ( ':' ) . ok_or ( ReadDirParseError ) ?;
439
+ let ( minute, second) = rest. split_once ( ':' ) . ok_or ( ReadDirParseError ) ?;
440
+
441
+ let size = size. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
442
+ let year = year. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
443
+ let month = month. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
444
+ let day = day. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
445
+ let hour = hour. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
446
+ let minute = minute. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
447
+ let second = second. parse ( ) . map_err ( |_| ReadDirParseError ) ?;
448
+
449
+ Ok ( Some ( MtftpFileInfo {
481
450
filename,
482
451
ip_address,
483
452
size,
@@ -487,9 +456,9 @@ impl BaseCode {
487
456
hour,
488
457
minute,
489
458
second,
490
- } )
491
- } )
492
- . fuse ( ) )
459
+ } ) )
460
+ } ;
461
+ Ok ( from_fn ( move || parse_next ( ) . transpose ( ) ) . fuse ( ) )
493
462
}
494
463
495
464
/// Writes a UDP packet to the network interface.
@@ -1274,3 +1243,8 @@ pub struct MtftpFileInfo<'a> {
1274
1243
pub minute : u8 ,
1275
1244
pub second : f32 ,
1276
1245
}
1246
+
1247
+ /// Returned if a server sends a malformed response in
1248
+ /// [`BaseCode::tftp_read_dir`] or [`BaseCode::mtftp_read_dir`].
1249
+ #[ derive( Clone , Copy , Debug ) ]
1250
+ pub struct ReadDirParseError ;
0 commit comments