1+ use std:: convert:: TryFrom ;
12use std:: fmt;
3+ use std:: iter;
4+ use std:: str:: FromStr ;
5+ use super :: EfiGuidError ;
6+ use types:: efi_guid_error;
27
8+ #[ derive( Debug , Clone , PartialEq , Eq , Copy ) ]
39pub struct EfiGuid {
410 a : u32 ,
511 b : u16 ,
@@ -15,8 +21,119 @@ impl fmt::Display for EfiGuid {
1521 }
1622}
1723
18- impl EfiGuid {
19- pub fn from_zero ( ) -> Self {
20- return Self { a : 0 , b : 0 , c : 0 , d : [ 0 ; 8 ] } ;
24+ macro_rules! from_byte_array {
25+ ( $type: ty) => {
26+ impl From <$type> for EfiGuid {
27+ fn from( value: $type) -> Self {
28+ return Self {
29+ a: ( u32 :: from( value[ 3 ] as u8 ) << 24 ) | ( u32 :: from( value[ 2 ] as u8 ) << 16 ) |
30+ ( u32 :: from( value[ 1 ] as u8 ) << 8 ) | ( u32 :: from( value[ 0 ] as u8 ) ) ,
31+ b: ( u16 :: from( value[ 5 ] as u8 ) << 8 ) | ( u16 :: from( value[ 4 ] as u8 ) ) ,
32+ c: ( u16 :: from( value[ 7 ] as u8 ) << 8 ) | ( u16 :: from( value[ 6 ] as u8 ) ) ,
33+ d: [
34+ ( value[ 8 ] as u8 ) , ( value[ 9 ] as u8 ) , ( value[ 10 ] as u8 ) , ( value[ 11 ] as u8 ) ,
35+ ( value[ 12 ] as u8 ) , ( value[ 13 ] as u8 ) , ( value[ 14 ] as u8 ) , ( value[ 15 ] as u8 ) ,
36+ ]
37+ } ;
38+ }
2139 }
40+ }
41+ }
42+
43+ macro_rules! from_byte_arrays {
44+ ( $type: ty) => {
45+ from_byte_array!( & [ $type; 16 ] ) ;
46+ from_byte_array!( & mut [ $type; 16 ] ) ;
47+ }
48+ }
49+
50+ macro_rules! try_from_byte_slice {
51+ ( $type: ty) => {
52+ impl TryFrom <& [ $type] > for EfiGuid {
53+ type Error = EfiGuidError ;
54+
55+ fn try_from( value: & [ $type] ) -> Result <Self , EfiGuidError > {
56+ let len = value. len( ) ;
57+
58+ return match <& [ $type; 16 ] >:: try_from( value) {
59+ Ok ( o) => Ok ( Self :: from( o) ) ,
60+ Err ( _) => if len < 16 { Err ( efi_guid_error:: SRC_SLICE_LENGTH_TOO_SHORT ) }
61+ else { Err ( efi_guid_error:: SRC_SLICE_LENGTH_TOO_LONG ) }
62+ }
63+ }
64+ }
65+ }
66+ }
67+
68+
69+ macro_rules! try_from_byte_vec {
70+ ( $type: ty) => {
71+ impl TryFrom <Vec <$type>> for EfiGuid {
72+ type Error = EfiGuidError ;
73+
74+ fn try_from( value: Vec <$type>) -> Result <Self , EfiGuidError > {
75+ let vec_len = value. len( ) ;
76+ match <[ $type; 16 ] >:: try_from( value) {
77+ Ok ( a) => Ok ( EfiGuid :: from( & a) ) ,
78+ Err ( _o) => if vec_len < 16 {
79+ Err ( efi_guid_error:: SRC_VEC_LENGTH_TOO_SHORT )
80+ } else {
81+ Err ( efi_guid_error:: SRC_VEC_LENGTH_TOO_LONG )
82+ }
83+ }
84+ }
85+ }
86+ }
87+ }
88+
89+ macro_rules! from_bytes {
90+ ( $type: ty) => {
91+ from_byte_arrays!( $type) ;
92+ try_from_byte_slice!( $type) ;
93+ try_from_byte_vec!( $type) ;
94+ } ;
95+ ( $type: ty, $( $types: ty) ,+) => {
96+ from_bytes!( $type) ;
97+ from_bytes!( $( $types) ,+) ;
98+ }
99+ }
100+
101+ from_bytes ! ( i8 , u8 ) ;
102+
103+
104+ impl FromStr for EfiGuid {
105+ type Err = EfiGuidError ;
106+
107+ fn from_str ( value : & str ) -> Result < Self , EfiGuidError > {
108+ let chars: Vec < char > = value. chars ( ) . into_iter ( ) . collect ( ) ;
109+ if chars. len ( ) != 36 {
110+ return Err ( efi_guid_error:: BAD_FORMAT ) ;
111+ }
112+ let digits = chars. into_iter ( ) . enumerate ( ) . filter_map ( |( i, c) | {
113+ if i == 8 || i == 13 || i == 18 || i == 23 {
114+ if c != '-' {
115+ return Some ( Err ( efi_guid_error:: BAD_FORMAT ) ) ;
116+ }
117+ return None ;
118+ }
119+ return match c. to_digit ( 16 ) {
120+ Some ( d) => Some ( Ok ( d as u8 ) ) ,
121+ None => Some ( Err ( efi_guid_error:: BAD_FORMAT ) ) ,
122+ }
123+ } )
124+ . collect :: < Result < Vec < u8 > , _ > > ( ) ?;
125+
126+ return Ok ( Self {
127+ a : digits[ 0 ..8 ] . iter ( ) . fold ( 0u32 , |sum, d| ( sum << 4 ) + u32:: from ( * d) ) ,
128+ b : digits[ 8 ..12 ] . iter ( ) . fold ( 0u16 , |sum, d| ( sum << 4 ) + u16:: from ( * d) ) ,
129+ c : digits[ 12 ..16 ] . iter ( ) . fold ( 0u16 , |sum, d| ( sum << 4 ) + u16:: from ( * d) ) ,
130+ d : match <[ u8 ; 8 ] >:: try_from ( iter:: zip (
131+ digits[ 16 ..] . into_iter ( ) . step_by ( 2 ) ,
132+ digits[ 16 ..] . into_iter ( ) . skip ( 1 ) . step_by ( 2 )
133+ ) . map ( |( h, l) | ( h << 4 ) + l) . collect :: < Vec < u8 > > ( ) ) {
134+ Ok ( o) => Ok ( o) ,
135+ Err ( _) => Err ( efi_guid_error:: BAD_FORMAT ) ,
136+ } . unwrap ( )
137+ } ) ;
138+ }
22139}
0 commit comments