@@ -253,6 +253,24 @@ impl PartialEq for DevicePathNode {
253253 }
254254}
255255
256+ impl < ' a > TryFrom < & [ u8 ] > for & ' a DevicePathNode {
257+ type Error = ByteConversionError ;
258+
259+ fn try_from ( bytes : & [ u8 ] ) -> Result < Self , Self :: Error > {
260+ if mem:: size_of :: < DevicePathHeader > ( ) <= bytes. len ( ) {
261+ let dp: & DevicePathHeader ;
262+ unsafe {
263+ dp = DevicePathHeader :: from_ffi_ptr ( bytes. as_ptr ( ) . cast ( ) ) ;
264+
265+ if dp. length as usize <= bytes. len ( ) {
266+ return Ok ( DevicePathNode :: from_ffi_ptr ( bytes. as_ptr ( ) . cast ( ) ) ) ;
267+ }
268+ }
269+ }
270+ Err ( ByteConversionError :: InvalidLength )
271+ }
272+ }
273+
256274/// A single device path instance that ends with either an [`END_INSTANCE`]
257275/// or [`END_ENTIRE`] node. Use [`DevicePath::instance_iter`] to get the
258276/// path instances in a [`DevicePath`].
@@ -729,6 +747,15 @@ impl DeviceSubType {
729747 pub const END_ENTIRE : DeviceSubType = DeviceSubType ( 0xff ) ;
730748}
731749
750+ /// Error returned when attempting to convert from a `&[u8]` to a
751+ /// [`DevicePath`] type using:
752+ /// - [`DevicePathNode::try_from`](struct.DevicePathNode.html#method.try_from)
753+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
754+ pub enum ByteConversionError {
755+ /// The length of the given slice is not valid for its [`DevicePath`] type.
756+ InvalidLength ,
757+ }
758+
732759/// Error returned when converting from a [`DevicePathNode`] to a more
733760/// specific node type.
734761#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
@@ -954,4 +981,41 @@ mod tests {
954981 let owned_dp_ref = & * owned_dp;
955982 assert_eq ! ( owned_dp_ref, dp)
956983 }
984+
985+ #[ test]
986+ fn test_device_path_from_bytes ( ) {
987+ let mut raw_data = Vec :: new ( ) ;
988+ let node = [ 0xa0 , 0xb0 ] ;
989+ let node_data = & [ 10 , 11 ] ;
990+ let mut dp;
991+
992+ // Raw data is less than size of a [`DevicePathNode`].
993+ raw_data. push ( node[ 0 ] ) ;
994+ dp = <& DevicePathNode >:: try_from ( raw_data. as_slice ( ) ) ;
995+ assert ! ( dp. is_err( ) ) ;
996+
997+ // Raw data is long enough to hold a [`DevicePathNode`].
998+ raw_data. push ( node[ 1 ] ) ;
999+ raw_data. extend (
1000+ u16:: try_from ( mem:: size_of :: < DevicePathHeader > ( ) + node_data. len ( ) )
1001+ . unwrap ( )
1002+ . to_le_bytes ( ) ,
1003+ ) ;
1004+ raw_data. extend ( node_data) ;
1005+ dp = <& DevicePathNode >:: try_from ( raw_data. as_slice ( ) ) ;
1006+ assert ! ( dp. is_ok( ) ) ;
1007+
1008+ // [`DevicePathNode`] data length exceeds the raw_data slice.
1009+ let mut raw_data = Vec :: new ( ) ;
1010+ raw_data. push ( node[ 0 ] ) ;
1011+ raw_data. push ( node[ 1 ] ) ;
1012+ raw_data. extend (
1013+ u16:: try_from ( mem:: size_of :: < DevicePathHeader > ( ) + 1 + node_data. len ( ) )
1014+ . unwrap ( )
1015+ . to_le_bytes ( ) ,
1016+ ) ;
1017+ raw_data. extend ( node_data) ;
1018+ dp = <& DevicePathNode >:: try_from ( raw_data. as_slice ( ) ) ;
1019+ assert ! ( dp. is_err( ) ) ;
1020+ }
9571021}
0 commit comments