@@ -13,29 +13,29 @@ use crate::utils::generic_iterator::GenericIterator;
13
13
use crate :: utils:: runtime:: tokio_block_on;
14
14
15
15
/// Implements standard file reading from local FS
16
- pub struct FileReader {
16
+ pub struct FileReader {
17
17
path : String ,
18
18
file : File ,
19
19
}
20
20
21
- struct DirectoryIteratorState {
21
+ struct DirectoryIteratorState {
22
22
objects : Vec < OsString > ,
23
23
current_object : usize ,
24
24
_full_path : OsString ,
25
25
}
26
26
27
27
impl DirectoryIteratorState {
28
- pub fn new ( path : String ) -> DirectoryIteratorState {
28
+ pub fn new ( path : String ) -> DirectoryIteratorState {
29
29
let path = Path :: new ( & path) ;
30
- let objects = if path. is_file ( ) {
30
+ let objects = if path. is_file ( ) {
31
31
vec ! [ OsString :: from( & path) ]
32
32
} else {
33
33
std:: fs:: read_dir ( path) . expect ( "Can not read directory" )
34
- . map ( |x| { x. unwrap ( ) . path ( ) . into_os_string ( ) } )
34
+ . map ( |x| { x. unwrap ( ) . path ( ) . into_os_string ( ) } )
35
35
. collect ( )
36
36
} ;
37
37
//println!("path {:?} has objects {:?}", path, objects);
38
- DirectoryIteratorState {
38
+ DirectoryIteratorState {
39
39
objects,
40
40
current_object : 0 ,
41
41
_full_path : OsString :: from ( & path) ,
@@ -44,12 +44,12 @@ impl DirectoryIteratorState {
44
44
45
45
#[ inline]
46
46
#[ allow( dead_code) ]
47
- pub fn len ( & self ) -> usize {
47
+ pub fn len ( & self ) -> usize {
48
48
self . objects . len ( )
49
49
}
50
50
51
- pub fn next_object ( & mut self ) -> Option < OsString > {
52
- if self . current_object >= self . objects . len ( ) {
51
+ pub fn next_object ( & mut self ) -> Option < OsString > {
52
+ if self . current_object >= self . objects . len ( ) {
53
53
None
54
54
} else {
55
55
let result = Some ( self . objects [ self . current_object ] . clone ( ) ) ;
@@ -64,64 +64,68 @@ struct DirectoryIterator {
64
64
state_stack : Vec < DirectoryIteratorState > ,
65
65
}
66
66
67
- impl DirectoryIterator {
68
- pub fn new ( url : & str ) -> DirectoryIterator {
69
- DirectoryIterator {
67
+ impl DirectoryIterator {
68
+ pub fn new ( url : & str ) -> DirectoryIterator {
69
+ DirectoryIterator {
70
70
_base_directory : url. to_string ( ) ,
71
71
state_stack : vec ! [ DirectoryIteratorState :: new( url. to_string( ) ) ] ,
72
72
}
73
73
}
74
74
}
75
75
76
- impl GenericIterator < String > for DirectoryIterator {
76
+ impl GenericIterator < String > for DirectoryIterator {
77
77
fn internal_next ( & mut self ) -> Option < String > {
78
- if self . state_stack . len ( ) == 0 {
78
+ if self . state_stack . len ( ) == 0 {
79
79
return None ;
80
80
}
81
81
let mut next_object = self . state_stack . last_mut ( ) . unwrap ( ) . next_object ( ) ;
82
82
//println!("next_object={:?}", next_object);
83
- while next_object. is_none ( ) && self . state_stack . len ( ) > 1 {
83
+ while next_object. is_none ( ) && self . state_stack . len ( ) > 1 {
84
84
self . state_stack . pop ( ) ;
85
85
next_object = self . state_stack . last_mut ( ) . unwrap ( ) . next_object ( ) ;
86
86
}
87
- if next_object. is_none ( ) {
87
+ if next_object. is_none ( ) {
88
88
//println!("No more objects through stack");
89
89
return None ;
90
90
}
91
91
let path_os_string = next_object. unwrap ( ) ;
92
92
let path_string = path_os_string. to_str ( ) . unwrap ( ) . to_string ( ) ;
93
- if Path :: new ( & path_os_string) . is_dir ( ) {
93
+ if Path :: new ( & path_os_string) . is_dir ( ) {
94
94
self . state_stack . push ( DirectoryIteratorState :: new ( path_string. clone ( ) ) ) ;
95
95
}
96
96
Some ( path_string)
97
97
}
98
98
}
99
99
100
100
101
+ #[ inline]
102
+ fn check_valid_url ( url : & str ) -> bool {
103
+ let re = Regex :: new ( r"^(/?[\s\w'.-]+)+(/)?$" ) . unwrap ( ) ;
104
+ re. is_match ( url)
105
+ }
101
106
102
107
#[ async_trait]
103
- impl Reader for FileReader {
108
+ impl Reader for FileReader {
104
109
fn can_read ( url : & str ) -> bool where Self : Sized {
105
- let re = Regex :: new ( r"^(/?[\w.-]+)+(/)?$" ) . unwrap ( ) ;
106
- if !re. is_match ( url) {
107
- return false
110
+ if !check_valid_url ( url) {
111
+ return false ;
108
112
}
109
113
let path = Path :: new ( url) ;
110
- if !path. is_file ( ) && !path. is_dir ( ) {
114
+ if !path. is_file ( ) && !path. is_dir ( ) {
111
115
println ! ( "{}:{} No such file or directory" , url. bold( ) . red( ) , "" . clear( ) ) ;
112
116
return false ;
113
117
}
114
118
true
115
119
}
116
120
fn new ( url : & str ) -> Self where Self : Sized {
117
- if !Self :: can_read ( url) {
121
+ if !Self :: can_read ( url) {
118
122
//panic!("Can not read url {url}");
119
123
}
120
124
let open_coroutine = async {
121
125
File :: open ( url) . await
122
126
} ;
123
-
124
- FileReader {
127
+
128
+ FileReader {
125
129
path : String :: from ( url) ,
126
130
file : tokio_block_on ( open_coroutine) . expect ( "Can not open file" ) ,
127
131
}
@@ -144,7 +148,7 @@ impl Reader for FileReader{
144
148
}
145
149
146
150
#[ inline]
147
- fn iter_directory ( url : & str ) -> Box < dyn GenericIterator < String > > {
151
+ fn iter_directory ( url : & str ) -> Box < dyn GenericIterator < String > > {
148
152
Box :: new ( DirectoryIterator :: new ( url) )
149
153
}
150
154
@@ -202,4 +206,15 @@ mod tests {
202
206
let url = "/tmp/документи/bar/file" ;
203
207
assert_eq ! ( FileReader :: relative_path( src_arg, url) , "tmp/документи/bar/file" ) ;
204
208
}
209
+
210
+ #[ test]
211
+ fn test_url_verifier ( ) {
212
+ assert ! ( check_valid_url( "The Folder/The File" ) ) ;
213
+ assert ! ( check_valid_url( "Teka/Łukasz" ) ) ;
214
+ assert ! ( check_valid_url( "/home/Łukasz/Pobrane/file.txt" ) ) ;
215
+ assert ! ( check_valid_url( "just_file_name" ) ) ;
216
+ assert ! ( check_valid_url( "просто_файл" ) ) ;
217
+ assert ! ( check_valid_url( "file' name" ) ) ;
218
+ assert ! ( !check_valid_url( "F:\\ windows\\ not_supported" ) ) ;
219
+ }
205
220
}
0 commit comments