@@ -397,6 +397,35 @@ impl DevicePath {
397
397
total_size_in_bytes
398
398
}
399
399
400
+ /// Calculate the size in bytes of the entire `DevicePath` starting
401
+ /// at `bytes`. This adds up each node's length, including the
402
+ /// end-entire node.
403
+ ///
404
+ /// # Errors
405
+ ///
406
+ /// The [`ByteConversionError::InvalidLength`] error will be returned
407
+ /// when the length of the given bytes slice cannot contain the full
408
+ /// [`DevicePath`] represented by the slice.
409
+ fn size_in_bytes_from_slice ( mut bytes : & [ u8 ] ) -> Result < usize , ByteConversionError > {
410
+ let max_size_in_bytes = bytes. len ( ) ;
411
+ let mut total_size_in_bytes: usize = 0 ;
412
+ loop {
413
+ let node = <& DevicePathNode >:: try_from ( bytes) ?;
414
+ let node_size_in_bytes = usize:: from ( node. length ( ) ) ;
415
+ total_size_in_bytes += node_size_in_bytes;
416
+ // Length of last processed node extends past the bytes slice.
417
+ if total_size_in_bytes > max_size_in_bytes {
418
+ return Err ( ByteConversionError :: InvalidLength ) ;
419
+ }
420
+ if node. is_end_entire ( ) {
421
+ break ;
422
+ }
423
+ bytes = & bytes[ node_size_in_bytes..] ;
424
+ }
425
+
426
+ Ok ( total_size_in_bytes)
427
+ }
428
+
400
429
/// Create a [`DevicePath`] reference from an opaque pointer.
401
430
///
402
431
/// # Safety
@@ -488,6 +517,15 @@ impl PartialEq for DevicePath {
488
517
}
489
518
}
490
519
520
+ impl < ' a > TryFrom < & [ u8 ] > for & ' a DevicePath {
521
+ type Error = ByteConversionError ;
522
+
523
+ fn try_from ( bytes : & [ u8 ] ) -> Result < Self , Self :: Error > {
524
+ let len = DevicePath :: size_in_bytes_from_slice ( bytes) ?;
525
+ unsafe { Ok ( & * ptr_meta:: from_raw_parts ( bytes. as_ptr ( ) . cast ( ) , len) ) }
526
+ }
527
+ }
528
+
491
529
#[ cfg( feature = "alloc" ) ]
492
530
impl ToOwned for DevicePath {
493
531
type Owned = Box < DevicePath > ;
@@ -1017,4 +1055,28 @@ mod tests {
1017
1055
raw_data[ 2 ] += 1 ;
1018
1056
assert ! ( <& DevicePathNode >:: try_from( raw_data. as_slice( ) ) . is_err( ) ) ;
1019
1057
}
1058
+
1059
+ #[ test]
1060
+ fn test_device_path_nodes_from_bytes ( ) {
1061
+ let raw_data = create_raw_device_path ( ) ;
1062
+ let dp = <& DevicePath >:: try_from ( raw_data. as_slice ( ) ) . unwrap ( ) ;
1063
+
1064
+ // Check that the size is the sum of the nodes' lengths.
1065
+ assert_eq ! ( mem:: size_of_val( dp) , 6 + 8 + 4 + 6 + 8 + 4 ) ;
1066
+
1067
+ // Check the list's node iter.
1068
+ let nodes: Vec < _ > = dp. node_iter ( ) . collect ( ) ;
1069
+ check_node ( nodes[ 0 ] , 0xa0 , 0xb0 , & [ 10 , 11 ] ) ;
1070
+ check_node ( nodes[ 1 ] , 0xa1 , 0xb1 , & [ 20 , 21 , 22 , 23 ] ) ;
1071
+ check_node (
1072
+ nodes[ 2 ] ,
1073
+ DeviceType :: END . 0 ,
1074
+ DeviceSubType :: END_INSTANCE . 0 ,
1075
+ & [ ] ,
1076
+ ) ;
1077
+ check_node ( nodes[ 3 ] , 0xa2 , 0xb2 , & [ 30 , 31 ] ) ;
1078
+ check_node ( nodes[ 4 ] , 0xa3 , 0xb3 , & [ 40 , 41 , 42 , 43 ] ) ;
1079
+ // The end-entire node is not returned by the iterator.
1080
+ assert_eq ! ( nodes. len( ) , 5 ) ;
1081
+ }
1020
1082
}
0 commit comments