@@ -10,79 +10,112 @@ use anyhow::Result;
10
10
use gix_attributes:: parse;
11
11
use gix_attributes:: parse:: Kind ;
12
12
13
- pub struct Attribute { }
13
+ const KEY_TYPE : & str = "type" ;
14
+ const VAL_EXTERNAL : & str = "external" ;
14
15
15
- impl Attribute {
16
+ pub struct Parser { }
17
+
18
+ #[ derive( Clone , Debug , Eq , PartialEq , Default ) ]
19
+ pub struct Item {
20
+ pub pattern : PathBuf ,
21
+ pub attributes : HashMap < String , String > ,
22
+ }
23
+
24
+ #[ derive( Clone , Debug , Eq , PartialEq , Default ) ]
25
+ pub struct Attributes {
26
+ pub items : Vec < Item > ,
27
+ }
28
+
29
+ impl Attributes {
16
30
/// Parse nydus attributes from a file.
17
- pub fn parse < P : AsRef < Path > > ( path : P ) -> Result < HashMap < PathBuf , u32 > > {
31
+ pub fn from < P : AsRef < Path > > ( path : P ) -> Result < Attributes > {
18
32
let content = fs:: read ( path) ?;
19
- let attributes = parse ( & content) ;
20
- let mut result = HashMap :: new ( ) ;
21
- for attribute in attributes {
22
- let attribute = attribute?;
23
- if let Kind :: Pattern ( pattern) = attribute. 0 {
24
- let mut path: Option < PathBuf > = None ;
25
- let mut backend_index: Option < u32 > = None ;
26
- for line in attribute. 1 {
27
- let line = line?;
28
- if line. name . as_str ( ) == "type"
29
- && line. state . as_bstr ( ) . unwrap_or_default ( ) == "external"
30
- {
31
- let _path = PathBuf :: from ( pattern. text . to_string ( ) ) ;
32
- if !_path. is_absolute ( ) {
33
- path = Some ( path:: Path :: new ( "/" ) . join ( _path) ) ;
34
- }
35
- }
36
- if line. name . as_str ( ) == "backend_index" {
37
- backend_index = Some (
38
- line. state
39
- . as_bstr ( )
40
- . unwrap_or_default ( )
41
- . to_string ( )
42
- . parse ( ) ?,
43
- ) ;
44
- }
33
+ let _items = parse ( & content) ;
34
+
35
+ let mut items = Vec :: new ( ) ;
36
+ for _item in _items {
37
+ let _item = _item?;
38
+ if let Kind :: Pattern ( pattern) = _item. 0 {
39
+ let mut path = PathBuf :: from ( pattern. text . to_string ( ) ) ;
40
+ if !path. is_absolute ( ) {
41
+ path = path:: Path :: new ( "/" ) . join ( path) ;
45
42
}
46
- match ( path, backend_index) {
47
- ( Some ( path) , Some ( backend_index) ) => {
48
- result. insert ( path, backend_index) ;
49
- }
50
- _ => { }
43
+ let mut attributes = HashMap :: new ( ) ;
44
+ for line in _item. 1 {
45
+ let line = line?;
46
+ let name = line. name . as_str ( ) ;
47
+ let state = line. state . as_bstr ( ) . unwrap_or_default ( ) ;
48
+ attributes. insert ( name. to_string ( ) , state. to_string ( ) ) ;
51
49
}
50
+ items. push ( Item {
51
+ pattern : path,
52
+ attributes,
53
+ } ) ;
52
54
}
53
55
}
54
- Ok ( result)
56
+
57
+ Ok ( Attributes { items } )
58
+ }
59
+
60
+ fn check_external ( & self , item : & Item ) -> bool {
61
+ item. attributes . get ( KEY_TYPE ) == Some ( & VAL_EXTERNAL . to_string ( ) )
62
+ }
63
+
64
+ pub fn is_external < P : AsRef < Path > > ( & self , path : P ) -> bool {
65
+ self . items
66
+ . iter ( )
67
+ . any ( |item| item. pattern == path. as_ref ( ) && self . check_external ( item) )
68
+ }
69
+
70
+ pub fn is_prefix_external < P : AsRef < Path > > ( & self , target : P ) -> bool {
71
+ self . items
72
+ . iter ( )
73
+ . any ( |item| item. pattern . starts_with ( & target) && self . check_external ( item) )
55
74
}
56
75
}
57
76
58
77
#[ cfg( test) ]
59
78
mod tests {
60
79
use std:: { collections:: HashMap , fs, path:: PathBuf } ;
61
80
62
- use super :: Attribute ;
81
+ use super :: { Attributes , Item } ;
63
82
use vmm_sys_util:: tempfile:: TempFile ;
64
83
65
84
#[ test]
66
85
fn test_attribute_parse ( ) {
67
86
let file = TempFile :: new ( ) . unwrap ( ) ;
68
87
fs:: write (
69
88
file. as_path ( ) ,
70
- "/foo type=external backend_index=0
71
- /bar type=external backend_index=0
72
- /models/foo type=external backend_index=1 " ,
89
+ "/foo type=external
90
+ /bar type=external
91
+ /models/foo type=external" ,
73
92
)
74
93
. unwrap ( ) ;
75
- let paths = Attribute :: parse ( file. as_path ( ) ) . unwrap ( ) ;
76
- assert_eq ! (
77
- paths,
78
- [
79
- ( PathBuf :: from( "/foo" ) , 0 ) ,
80
- ( PathBuf :: from( "/bar" ) , 0 ) ,
81
- ( PathBuf :: from( "/models/foo" ) , 1 )
82
- ]
94
+
95
+ let attributes = Attributes :: from ( file. as_path ( ) ) . unwrap ( ) ;
96
+ let _attributes: HashMap < String , String > = [ ( "type" . to_string ( ) , "external" . to_string ( ) ) ]
83
97
. iter ( )
84
98
. cloned ( )
85
- . collect:: <HashMap <PathBuf , u32 >>( )
99
+ . collect ( ) ;
100
+
101
+ assert_eq ! (
102
+ attributes,
103
+ Attributes {
104
+ items: vec![
105
+ Item {
106
+ pattern: PathBuf :: from( "/foo" ) ,
107
+ attributes: _attributes. clone( )
108
+ } ,
109
+ Item {
110
+ pattern: PathBuf :: from( "/bar" ) ,
111
+ attributes: _attributes. clone( )
112
+ } ,
113
+ Item {
114
+ pattern: PathBuf :: from( "/models/foo" ) ,
115
+ attributes: _attributes. clone( )
116
+ }
117
+ ]
118
+ } ,
86
119
) ;
87
120
}
88
121
}
0 commit comments