@@ -397,6 +397,35 @@ impl DevicePath {
397397 total_size_in_bytes
398398 }
399399
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+
400429 /// Create a [`DevicePath`] reference from an opaque pointer.
401430 ///
402431 /// # Safety
@@ -488,6 +517,15 @@ impl PartialEq for DevicePath {
488517 }
489518}
490519
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+
491529#[ cfg( feature = "alloc" ) ]
492530impl ToOwned for DevicePath {
493531 type Owned = Box < DevicePath > ;
@@ -1017,4 +1055,28 @@ mod tests {
10171055 raw_data[ 2 ] += 1 ;
10181056 assert ! ( <& DevicePathNode >:: try_from( raw_data. as_slice( ) ) . is_err( ) ) ;
10191057 }
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+ }
10201082}
0 commit comments