@@ -396,6 +396,35 @@ impl DevicePath {
396396 total_size_in_bytes
397397 }
398398
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+
399428 /// Create a [`DevicePath`] reference from an opaque pointer.
400429 ///
401430 /// # Safety
@@ -487,6 +516,15 @@ impl PartialEq for DevicePath {
487516 }
488517}
489518
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+
490528#[ cfg( feature = "alloc" ) ]
491529impl ToOwned for DevicePath {
492530 type Owned = Box < DevicePath > ;
@@ -1016,4 +1054,28 @@ mod tests {
10161054 raw_data[ 2 ] += 1 ;
10171055 assert ! ( <& DevicePathNode >:: try_from( raw_data. as_slice( ) ) . is_err( ) ) ;
10181056 }
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+ }
10191081}
0 commit comments