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