file_ext/
lib.rs

1use std::fs::{File};
2use crate::date_time_ext::DateTimeExt;
3use crate::directory_ext_impl::DirectoryExtImpl;
4use crate::file_ext_impl::FileExtImpl;
5use crate::path_ext_impl::PathExtImpl;
6use crate::symbol::SYMBOL;
7use crate::symlink_ext_impl::SymlinkExtImpl;
8use crate::user_ext_impl::UserExtImpl;
9
10#[cfg(test)]
11mod tests;
12mod date_time_ext;
13mod symbol;
14mod file_ext_impl;
15mod path_ext_impl;
16mod directory_ext_impl;
17mod symlink_ext_impl;
18mod user_ext_impl;
19mod filter_string;
20
21pub struct FileExt;
22
23impl FileExt {
24
25    /// Returns portion of a file of specified range. Range described as starting from byte M up to byte N.
26    /// # Examples
27    ///
28    /// ```
29    /// use file_ext::FileExt;
30    /// #[test]
31    /// fn partial_read() {
32    ///     let path = "test/index.html";
33    ///     let file_raw_bytes = FileExt::read_file_partially(path, 4, 10).unwrap();
34    ///     let content = String::from_utf8(file_raw_bytes).unwrap();
35    ///
36    ///     let expected_content = "CTYPE h";
37    ///
38    ///     assert_eq!(expected_content, content);
39    /// }
40    /// ```
41    pub fn read_file_partially(filepath: &str, start: u64, end: u64) -> Result<Vec<u8>, String> {
42        FileExtImpl::read_file_partially(filepath, start, end)
43    }
44
45    /// Returns file content
46    /// # Examples
47    ///
48    /// ```
49    ///  use file_ext::FileExt;
50    ///  #[test]
51    ///  fn file_content() {
52    ///      let path = "test/index.html";
53    ///      let file_raw_bytes = FileExt::read_file(path).unwrap();
54    ///      let content = String::from_utf8(file_raw_bytes).unwrap();
55    ///  
56    ///      let content_escaped_newline_carriage_return = str::replace(content.as_str(), "\r\n", "\n");
57    ///
58    ///      let expected_content = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Title</title>\n</head>\n<body>\n\n</body>\n</html>";
59    ///
60    ///      assert_eq!(expected_content, content_escaped_newline_carriage_return);
61    ///  }
62    /// ```
63    pub fn read_file(filepath: &str) -> Result<Vec<u8>, String> {
64        FileExtImpl::read_file(filepath)
65    }
66
67    /// Returns file modification timestamp as nanoseconds in Unix epoch
68    /// # Examples
69    ///
70    /// ```
71    ///  use std::{thread, time};
72    ///  use file_ext::FileExt;
73    ///  #[test]
74    ///  fn modification_timestamp() {
75    ///
76    ///      let content = "data".as_bytes();
77    ///      let path = "modification_timestamp-test.content";
78    ///
79    ///      FileExt::create_file(path).unwrap();
80    ///      FileExt::write_file(path, content).unwrap();
81    ///
82    ///      let does_exist = FileExt::does_file_exist(path);
83    ///      assert!(does_exist);
84    ///
85    ///      let modified_timestamp = FileExt::file_modified_utc(path).unwrap();
86    ///
87    ///      let one_second = time::Duration::from_secs(1);
88    ///      thread::sleep(one_second);
89    ///
90    ///      FileExt::write_file(path, "\nnewline and some data".as_bytes()).unwrap();
91    ///
92    ///      let after_update_modified_timestamp = FileExt::file_modified_utc(path).unwrap();
93    ///      assert!(after_update_modified_timestamp > modified_timestamp);
94    ///
95    ///
96    ///      FileExt::delete_file(path).unwrap();
97    ///      let doesnt_exist = !FileExt::does_file_exist(path);
98    ///      assert!(doesnt_exist);
99    ///  }
100    /// ```
101    pub fn file_modified_utc(filepath: &str) -> Result<u128, String> {
102        let boxed_open = File::open(filepath);
103        if boxed_open.is_err() {
104            let error_msg = boxed_open.err().unwrap();
105            let error = format!("<p>Unable to open file: {}</p> <p>error: {}</p>", filepath, error_msg);
106            return Err(error)
107        }
108
109        let file : File = boxed_open.unwrap();
110        let boxed_metadata = file.metadata();
111        if boxed_metadata.is_err() {
112            let error_msg = boxed_metadata.err().unwrap();
113            let error = format!("<p>Unable to open file: {}</p> <p>error: {}</p>", filepath, error_msg);
114            return Err(error)
115        }
116        let metadata = boxed_metadata.unwrap();
117        let boxed_last_modified_time = metadata.modified();
118        if boxed_last_modified_time.is_err() {
119            let error_msg = boxed_last_modified_time.err().unwrap();
120            let error = format!("<p>Unable to open file: {}</p> <p>error: {}</p>", filepath, error_msg);
121            return Err(error)
122        }
123        let modified_time = boxed_last_modified_time.unwrap();
124        let nanos = DateTimeExt::_system_time_to_unix_nanos(modified_time);
125        Ok(nanos)
126    }
127
128    #[cfg(target_family = "unix")]
129    /// # Examples
130    ///
131    /// ```
132    /// use file_ext::FileExt;
133    /// #[test]
134    /// fn unix_path_delimiter() {
135    ///     let expected = SYMBOL.slash.to_string();
136    ///     let actual = FileExt::get_path_separator();
137    /// }
138    /// ```
139    pub fn get_path_separator() -> String {
140        PathExtImpl::get_path_separator()
141    }
142
143    #[cfg(target_family = "windows")]
144    /// # Examples
145    ///
146    /// ```
147    /// use file_ext::FileExt;
148    /// #[test]
149    /// fn unix_path_delimiter() {
150    ///     let expected = SYMBOL.reverse_slash.to_string();
151    ///     let actual = FileExt::get_path_separator();
152    /// }
153    /// ```
154    pub fn get_path_separator() -> String { PathExtImpl::get_path_separator() }
155
156    /// Will return absolute file path to the working directory
157    /// # Examples
158    ///
159    /// ```
160    /// use file_ext::FileExt;
161    /// #[test]
162    /// fn absolute_path_to_working_directory() {
163    ///     let boxed_path = FileExt::working_directory();
164    ///     assert!(boxed_path.is_ok());
165    ///     let path = boxed_path.unwrap();
166    /// }
167    /// ```
168    pub fn working_directory() -> Result<String, String> {
169        PathExtImpl::working_directory()
170    }
171
172
173    /// Will return absolute file path to the working directory. Same as working_directory function. Kept here to preserve backward compatability.
174    /// # Examples
175    ///
176    /// ```
177    /// use file_ext::FileExt;
178    /// #[test]
179    /// fn absolute_path_to_working_directory() {
180    ///     let boxed_path = FileExt::absolute_path_to_working_directory();
181    ///     assert!(boxed_path.is_ok());
182    ///     let path = boxed_path.unwrap();
183    /// }
184    /// ```
185    pub fn absolute_path_to_working_directory() -> Result<String, String> {
186        PathExtImpl::working_directory()
187    }
188
189
190    /// Will return absolute working directory path appended to the given string
191    /// # Examples
192    ///
193    /// ```
194    /// use file_ext::FileExt;
195    /// #[test]
196    /// fn absolute_path_to_working_directory() {
197    ///     let boxed_path = FileExt::get_static_filepath("");
198    ///     assert!(boxed_path.is_ok());
199    ///     let path = boxed_path.unwrap();
200    /// }
201    /// ```
202    pub fn get_static_filepath(path: &str) -> Result<String, String> {
203        let boxed_working_directory = PathExtImpl::absolute_path_to_working_directory();
204        if boxed_working_directory.is_err() {
205            let message = boxed_working_directory.err().unwrap();
206            return Err(message)
207        }
208
209        let working_directory = boxed_working_directory.unwrap();
210        let absolute_path = [working_directory, path.to_string()].join(SYMBOL.empty_string);
211        Ok(absolute_path)
212    }
213
214    /// Will try to read from file. If file does not exist, will create and write to it given byte array
215    /// # Examples
216    ///
217    /// ```
218    ///  use file_ext::FileExt;
219    ///  #[test]
220    ///  fn read_or_create_and_write() {
221    ///      let content = "data".as_bytes();
222    ///      let tmp_folder = FileExt::get_temp_folder_path().unwrap();
223    ///
224    ///      let path = [tmp_folder, "test.txt".to_string()].join(FileExt::get_path_separator().as_str());
225    ///
226    ///      let doesnt_exist = !FileExt::does_file_exist(path.as_str());
227    ///      assert!(doesnt_exist);
228    ///
229    ///      FileExt::read_or_create_and_write(path.as_str(), content).unwrap();
230    ///
231    ///      let does_exist = FileExt::does_file_exist(path.as_str());
232    ///      assert!(does_exist);
233    ///
234    ///      let new_content = "updated data".as_bytes();
235    ///      FileExt::read_or_create_and_write(path.as_str(), new_content).unwrap();
236    ///
237    ///      let file_content = FileExt::read_file(path.as_str()).unwrap();
238    ///      assert_eq!(content, file_content);
239    ///
240    ///      FileExt::delete_file(path.as_str()).unwrap();
241    ///      let doesnt_exist = !FileExt::does_file_exist(path.as_str());
242    ///      assert!(doesnt_exist);
243    ///  }
244    /// ```
245    pub fn read_or_create_and_write(path: &str, content: &[u8]) -> Result<Vec<u8>, String> {
246        FileExtImpl::read_or_create_and_write(path, content)
247    }
248
249    /// Will create a file on the path
250    /// # Examples
251    ///
252    /// ```
253    /// use file_ext::FileExt;
254    /// #[test]
255    /// fn file_creation_deletion() {
256    ///     let path = "test/file-creation.txt";
257    ///
258    ///     let exists = FileExt::does_file_exist(path);
259    ///     assert!(!exists);
260    ///
261    ///     FileExt::create_file(path).unwrap();
262    ///
263    ///     let content = FileExt::read_file(path).unwrap();
264    ///     assert_eq!(content.len(), 0);
265    ///
266    ///     FileExt::delete_file(path).unwrap();
267    ///
268    ///     let exists = FileExt::does_file_exist(path);
269    ///     assert!(!exists);
270    /// }
271    /// ```
272    pub fn create_file(path: &str) -> Result<(), String>  {
273        FileExtImpl::create_file(path)
274    }
275
276    /// Returns boolean indicating file existence on the path
277    /// # Examples
278    ///
279    /// ```
280    /// use file_ext::FileExt;
281    /// #[test]
282    /// fn file_exists() {
283    ///     let path = "test/index_rewrite";
284    ///     let exists = FileExt::does_file_exist(path);
285    ///     assert!(exists);
286    /// }
287    /// ```
288    pub fn does_file_exist(path: &str) -> bool {
289        FileExtImpl::does_file_exist(path)
290    }
291
292    /// Returns boolean indicating directory existence on the path
293    /// # Examples
294    ///
295    /// ```
296    /// use file_ext::FileExt;
297    /// #[test]
298    /// fn directory_exists() {
299    ///     let path = "test";
300    ///     let exists = FileExt::does_directory_exist(path);
301    ///     assert!(exists);
302    /// }
303    /// ```
304    pub fn does_directory_exist(path: &str) -> bool {
305        DirectoryExtImpl::does_directory_exist(path)
306    }
307
308
309    /// Will create a new directory on specified path
310    /// # Examples
311    ///
312    /// ```
313    ///  use file_ext::FileExt;
314    ///  #[test]
315    ///  fn new_directory_create_delete() {
316    ///      let path = "new_directory";
317    ///
318    ///      let boxed_create = FileExt::create_directory(path);
319    ///      assert!(boxed_create.is_ok());
320    ///
321    ///      assert!(FileExt::does_directory_exist(path));
322    ///
323    ///      let boxed_delete = FileExt::delete_directory(path);
324    ///      assert!(boxed_delete.is_ok());
325    ///  }
326    /// ```
327    pub fn create_directory(path: &str) -> Result<(), String> {
328        DirectoryExtImpl::create_directory(path)
329    }
330
331    /// Will delete directory and all of the content on specified path (won't follow symlinks)
332    /// # Examples
333    ///
334    /// ```
335    ///  use file_ext::FileExt;
336    ///  #[test]
337    ///  fn new_directory_create_delete() {
338    ///      let path = "new_directory";
339    ///
340    ///      let boxed_create = FileExt::create_directory(path);
341    ///      assert!(boxed_create.is_ok());
342    ///
343    ///      assert!(FileExt::does_directory_exist(path));
344    ///
345    ///      let boxed_delete = FileExt::delete_directory(path);
346    ///      assert!(boxed_delete.is_ok());
347    ///  }
348    /// ```
349    pub fn delete_directory(path: &str) -> Result<(), String> {
350        DirectoryExtImpl::delete_directory(path)
351    }
352
353
354    /// Returns boolean indicating symlink existence on the path
355    /// # Examples
356    ///
357    /// ```
358    /// use file_ext::FileExt;
359    /// #[test]
360    /// fn symlink_exists() {
361    ///   let symlink_path = ["test", "index-link2"].join(FileExt::get_path_separator().as_str());
362    ///
363    ///   if FileExt::does_symlink_exist(symlink_path.as_str()) {
364    ///     FileExt::delete_file(symlink_path.as_str()).unwrap();
365    ///   }
366    ///
367    ///   let path = [SYMBOL.empty_string, "test", SYMBOL.empty_string].join(FileExt::get_path_separator().as_str());
368    ///   let path_prefix = FileExt::get_static_filepath(path.as_str()).unwrap();
369    ///   let points_to = [path_prefix.to_string(), "index.html".to_string()].join("");
370    ///
371    ///   let boxed_symlink = FileExt::create_symlink(
372    ///     path_prefix.as_str(),
373    ///     "index-link2",
374    ///     points_to.as_str()
375    ///   );
376    ///
377    ///
378    ///   assert!(boxed_symlink.is_ok());
379    ///
380    ///   let symlink_created = FileExt::does_symlink_exist(symlink_path.as_str());
381    ///   assert!(symlink_created);
382    ///
383    ///   let actual_points_to = FileExt::symlink_points_to(symlink_path.as_str()).unwrap();
384    ///   assert_eq!(points_to, actual_points_to);
385    ///
386    ///   FileExt::delete_file(symlink_path.as_str()).unwrap();
387    /// }
388    /// ```
389    pub fn does_symlink_exist(path: &str) -> bool {
390        SymlinkExtImpl::does_symlink_exist(path)
391    }
392
393    /// Returns absolute path, symlink points to.
394    /// Takes 2 parameters: path to the directory, where symlink is located and where symlink points to
395    /// # Examples
396    ///
397    /// ```
398    /// use file_ext::FileExt;
399    /// #[test]
400    /// fn resolve_symlink_path() {
401    ///    let base_dir = "/home/someuser/folder/subfolder/subsubfolder";
402    ///    let symlink_points_to = "../../subfolder2/subsubfolder2";
403    ///
404    ///    let expected_path = "/home/someuser/folder/subfolder2/subsubfolder2";
405    ///    let actual_path = FileExt::resolve_symlink_path(base_dir, symlink_points_to).unwrap();
406    ///
407    ///    assert_eq!(expected_path, actual_path);
408    /// }
409    /// ```
410    pub fn resolve_symlink_path(symlink_directory: &str, symlink_points_to: &str) -> Result<String, String> {
411        SymlinkExtImpl::resolve_symlink_path(symlink_directory, symlink_points_to)
412    }
413
414    /// Will write given byte array to a file on the path
415    /// # Examples
416    /// ```
417    ///  use file_ext::FileExt;
418    /// #[test]
419    ///  fn write() {
420    ///      let filename = "write-test.content";
421    ///      FileExt::create_file(filename).unwrap();
422    ///
423    ///      let expected_content = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Title</title>\n</head>\n<body>\n\n</body>\n</html>";
424    ///      FileExt::write_file(filename, expected_content.as_bytes()).unwrap();
425    ///
426    ///      let actual = FileExt::read_file(filename).unwrap();
427    ///      assert_eq!(actual, expected_content.as_bytes());
428    ///
429    ///  }
430    /// ```
431    pub fn write_file(path: &str, file_content: &[u8]) -> Result<(), String> {
432        FileExtImpl::write_file(path, file_content)
433    }
434
435    /// Will delete file on a given path
436    /// # Examples
437    ///
438    /// ```
439    /// use file_ext::FileExt;
440    /// #[test]
441    /// fn file_creation_deletion() {
442    ///     let path = "test/file-creation.txt";
443    ///
444    ///     let exists = FileExt::does_file_exist(path);
445    ///     assert!(!exists);
446    ///
447    ///     FileExt::create_file(path).unwrap();
448    ///
449    ///     let content = FileExt::read_file(path).unwrap();
450    ///     assert_eq!(content.len(), 0);
451    ///
452    ///     FileExt::delete_file(path).unwrap();
453    ///
454    ///     let exists = FileExt::does_file_exist(path);
455    ///     assert!(!exists);
456    /// }
457    /// ```
458    pub fn delete_file(path: &str) -> Result<(), String> {
459        FileExtImpl::delete_file(path)
460    }
461
462    /// Will create symlink on path `symlink_path` with the specified name `symlink_name`.
463    /// Symlink will point to specific file or directory `symlink_points_to`. Paths are absolute.
464    /// # Examples
465    /// ```
466    /// use file_ext::FileExt;
467    /// #[test]
468    ///fn symlink_creation() {
469    ///    let symlink_path = "test/index-link";
470    ///
471    ///    if FileExt::does_symlink_exist(symlink_path) {
472    ///        FileExt::delete_file(symlink_path).unwrap();
473    ///    }
474    ///
475    ///    let path_prefix = FileExt::get_static_filepath("/test/").unwrap();
476    ///    let points_to = [path_prefix.to_string(), "index.html".to_string()].join("");
477    ///
478    ///    let boxed_symlink = FileExt::create_symlink(
479    ///        path_prefix.as_str(),
480    ///        "index-link",
481    ///        points_to.as_str());
482    ///
483    ///     assert!(boxed_symlink.is_ok());
484    ///
485    ///     let symlink_created = FileExt::does_symlink_exist(symlink_path);
486    ///     assert!(symlink_created);
487    ///
488    ///     let actual_points_to = FileExt::symlink_points_to(symlink_path).unwrap();
489    ///     assert_eq!(points_to, actual_points_to);
490    ///
491    ///     FileExt::delete_file(symlink_path).unwrap();
492    ///}
493    ///```
494    #[cfg(target_family = "unix")]
495    pub fn create_symlink(symlink_path: &str, symlink_name: &str, symlink_points_to: &str) -> Result<(), String> {
496        SymlinkExtImpl::create_symlink(symlink_path, symlink_name, symlink_points_to)
497    }
498
499
500    /// Will create symlink on path `symlink_path` with the specified name `symlink_name`.
501    /// Symlink will point to specific file or directory `symlink_points_to`. Paths are absolute.
502    /// # Examples
503    /// ```
504    /// use file_ext::FileExt;
505    /// #[test]
506    ///fn symlink_creation() {
507    ///    let symlink_path = "test/index-link";
508    ///
509    ///    if FileExt::does_symlink_exist(symlink_path) {
510    ///        FileExt::delete_file(symlink_path).unwrap();
511    ///    }
512    ///
513    ///    let path_prefix = FileExt::get_static_filepath("/test/").unwrap();
514    ///    let points_to = [path_prefix.to_string(), "index.html".to_string()].join("");
515    ///
516    ///    let boxed_symlink = FileExt::create_symlink(
517    ///        path_prefix.as_str(),
518    ///        "index-link",
519    ///        points_to.as_str());
520    ///
521    ///        assert!(boxed_symlink.is_ok());
522    ///
523    ///        let symlink_created = FileExt::does_symlink_exist(symlink_path);
524    ///        assert!(symlink_created);
525    ///
526    ///        let actual_points_to = FileExt::symlink_points_to(symlink_path).unwrap();
527    ///        assert_eq!(points_to, actual_points_to);
528    ///
529    ///        FileExt::delete_file(symlink_path).unwrap();
530    ///}
531    ///```
532    #[cfg(target_family = "windows")]
533    pub fn create_symlink(symlink_path: &str, symlink_name: &str, symlink_points_to: &str) -> Result<(), String> {
534        SymlinkExtImpl::create_symlink(symlink_path, symlink_name, symlink_points_to)
535    }
536
537    /// Checks if the file is symlink
538    /// # Examples
539    ///
540    /// ```
541    /// use file_ext::FileExt;
542    /// #[test]
543    /// fn is_link() {
544    ///     let path: String = ["test", "index_rewrite"].join(&FileExt::get_path_separator());
545    ///     let is_symlink = FileExt::is_symlink(path.as_str()).unwrap();
546    ///     assert!(is_symlink);
547    /// }
548    /// ```
549    pub fn is_symlink(path: &str) -> Result<bool, String> {
550        SymlinkExtImpl::is_symlink(path)
551    }
552
553    /// Returns path to a file, symlink points to
554    /// # Examples
555    ///
556    /// ```
557    /// use file_ext::FileExt;
558    /// #[test]
559    /// fn link_points_to() {
560    ///     let path: String = ["test", "index_rewrite"].join(&FileExt::get_path_separator());
561    ///     let points_to = FileExt::symlink_points_to(path.as_str()).unwrap();
562    ///     assert_eq!("index.html", points_to);
563    /// }
564    /// ```
565    pub fn symlink_points_to(path: &str) -> Result<String, String> {
566        SymlinkExtImpl::symlink_points_to(path)
567    }
568
569    /// Builds a path from a given node list
570    /// # Examples
571    ///
572    /// ```
573    /// use file_ext::FileExt;
574    ///
575    /// #[test]
576    /// #[cfg(target_family = "unix")]
577    /// fn build_path() {
578    ///     let root = FileExt::root();
579    ///     let folder_up = FileExt::folder_up();
580    ///
581    ///     let node_list =
582    ///         [
583    ///             root.as_str(),
584    ///             "home",
585    ///             "someuser",
586    ///             "folder",
587    ///             "subfolder",
588    ///             "subsubfolder",
589    ///         ];
590    ///
591    ///     let another_node_list =
592    ///         [
593    ///             folder_up.as_str(),
594    ///             folder_up.as_str(),
595    ///             "subfolder2",
596    ///             "subsubfolder2",
597    ///         ];
598    ///     let path = PathExtImpl::build_path(&node_list);
599    ///     let another_path = PathExtImpl::build_path(&another_node_list);
600    ///
601    ///     assert_eq!("/home/someuser/folder/subfolder/subsubfolder", path);
602    ///     assert_eq!("../../subfolder2/subsubfolder2", another_path);
603    /// }
604    ///
605    ///
606    /// #[test]
607    /// #[cfg(target_family = "windows")]
608    /// fn build_path() {
609    ///     let root = FileExt::root();
610    ///     let folder_up = FileExt::folder_up();
611    ///
612    ///     let node_list =
613    ///         [
614    ///             root.as_str(),
615    ///             "Users",
616    ///             "someuser",
617    ///             "folder",
618    ///             "subfolder",
619    ///             "subsubfolder",
620    ///         ];
621    ///
622    ///     let path = PathExtImpl::build_path(&node_list);
623    ///
624    ///     assert_eq!("C:\\Users\\someuser\\folder\\subfolder\\subsubfolder", path);
625    /// }
626    /// ```
627    pub fn build_path(list: &[&str]) -> String {
628        PathExtImpl::build_path(list)
629    }
630
631    /// Root node of the system. It is meant to be used in `build_path` function.
632    /// On Linux and macOS `build_path` function will evaluate it to `/`,
633    /// on Windows it will be `C:`
634    pub fn root() -> String {
635        PathExtImpl::root()
636    }
637
638
639    /// Folder up, or `..`. It is meant to be used in `build_path` function.
640    pub fn folder_up() -> String {
641        PathExtImpl::folder_up()
642    }
643
644    /// Returns name of the user running the process
645    /// # Examples
646    ///
647    /// ```
648    ///  use file_ext::FileExt;
649    ///  #[test]
650    ///  #[cfg(target_family = "unix")]
651    ///  fn current_user() {
652    ///      let boxed_user = FileExt::get_current_user();
653    ///      assert!(boxed_user.is_ok());
654    ///
655    ///      let user = boxed_user.unwrap();
656    ///  }
657    /// ```
658    #[cfg(target_family = "unix")]
659    pub fn get_current_user() -> Result<String, String> {
660        UserExtImpl::get_current_user()
661    }
662
663    /// Returns name of the user running the process
664    /// # Examples
665    ///
666    /// ```
667    ///  use file_ext::FileExt;
668    ///  #[test]
669    ///  #[cfg(target_family = "windows")]
670    ///  fn current_user() {
671    ///      let boxed_user = FileExt::get_current_user();
672    ///      assert!(boxed_user.is_ok());
673    ///
674    ///      let user = boxed_user.unwrap();
675    ///  }
676    /// ```
677    #[cfg(target_family = "windows")]
678    pub fn get_current_user() -> Result<String, String> {
679        UserExtImpl::get_current_user()
680    }
681
682    /// Returns domain of the user running the process
683    /// # Examples
684    ///
685    /// ```
686    ///  use file_ext::FileExt;
687    ///  #[test]
688    ///  #[cfg(target_family = "windows")]
689    ///  fn current_user() {
690    ///      let boxed_user_domain = FileExt::get_current_user_domain();
691    ///      assert!(boxed_user_domain.is_ok());
692    ///
693    ///      let domain = boxed_user_domain.unwrap();
694    ///  }
695    /// ```
696    #[cfg(target_family = "windows")]
697    pub fn get_current_user_domain() -> Result<String, String> {
698        UserExtImpl::get_current_user_domain()
699    }
700
701    /// Returns path to the temporary folder
702    /// # Examples
703    ///
704    /// ```
705    ///  use file_ext::FileExt;
706    ///  #[test]
707    ///  #[cfg(target_family = "windows")]
708    ///  fn temp_folder() {
709    ///      let temp_folder_path = FileExt::get_temp_folder_path().unwrap();
710    ///      assert!(temp_folder_path.starts_with("C:\\Users\\"));
711    ///      assert!(temp_folder_path.ends_with("\\AppData\\Local\\Temp"));
712    ///  }
713    /// ```
714    #[cfg(target_family = "windows")]
715    pub fn get_temp_folder_path() -> Result<String, String>{
716        PathExtImpl::get_temp_folder_path()
717    }
718
719    /// Returns path to the temporary folder
720    /// # Examples
721    ///
722    /// ```
723    ///  use file_ext::FileExt;
724    ///  #[test]
725    ///  #[cfg(target_family = "unix")]
726    ///  fn temp_folder() {
727    ///      let temp_folder_path = FileExt::get_temp_folder_path().unwrap();
728    ///      assert_eq!(temp_folder_path, "/tmp")
729    ///  }
730    /// ```
731    #[cfg(target_family = "unix")]
732    pub fn get_temp_folder_path() -> Result<String, String>{
733        PathExtImpl::get_temp_folder_path()
734    }
735
736    /// Returns file length in bytes
737    ///```
738    /// use file_ext::FileExt;
739    /// #[test]
740    /// fn length() {
741    ///    let expected_length: u64 = 398;
742    ///    let pwd = FileExt::working_directory().unwrap();
743    ///    let length = FileExt::file_length(vec![pwd.as_str(), "LICENSE"]).unwrap();
744    ///
745    ///    assert_eq!(expected_length, length);
746    /// }
747    /// ```
748    pub fn file_length(path: Vec<&str>) -> Result<u64, String> {
749        FileExtImpl::file_length(path)
750    }
751
752    /// Copies file block by block. Block size is 100kb
753    ///```
754    /// use file_ext::FileExt;
755    /// #[test]
756    /// fn copy_file() {
757    ///     let pwd = FileExt::working_directory().unwrap();
758    ///     FileExt::copy_file(vec![pwd.as_str(), "LICENSE"], vec![pwd.as_str(), "LICENSE_copy2"]).unwrap();
759    ///
760    ///     let path = FileExt::build_path(vec![pwd.as_str(), "LICENSE_copy2"].as_slice());
761    ///     FileExt::delete_file(path.as_str()).unwrap();
762    /// }
763    /// ```
764    pub fn copy_file(from: Vec<&str>, to: Vec<&str>)-> Result<(), String> {
765        FileExtImpl::copy_file(from, to)
766    }
767
768    /// Copies file block by block. If block size is None it is set to 100kb.
769    /// Calls the progress callback at the beginning of the block copy.
770    /// Calls the cancel callback at the end of the block copy.
771    ///```
772    /// use file_ext::FileExt;
773    /// #[test]
774    /// fn copy_file_with_callback_and_block_size() {
775    ///     let block_size : u64 = 1000000;
776    ///     let pwd = FileExt::working_directory().unwrap();
777    ///     let mut label = "".to_string();
778    ///     let progress_callback = |start, end, total| { label = format!("copying block {}-{} of {} bytes", start, end, total).to_string(); };
779    ///     let cancel_callback = |_start, _end, _total| { false };
780    ///     FileExt::copy_file_with_callbacks(
781    ///         vec![pwd.as_str(), "LICENSE"],
782    ///         vec![pwd.as_str(), "LICENSE_copy3"],
783    ///         Some(block_size),
784    ///         progress_callback,
785    ///         cancel_callback
786    ///     ).unwrap();
787    ///
788    ///     let path = FileExt::build_path(vec![pwd.as_str(), "LICENSE_copy3"].as_slice());
789    ///     FileExt::delete_file(path.as_str()).unwrap();
790    /// }
791    ///```
792    pub fn copy_file_with_callbacks<F: FnMut(u64, u64, u64), C: FnMut(u64, u64, u64) -> bool>
793                (
794                    from: Vec<&str>,
795                    to: Vec<&str>,
796                    block_size: Option<u64>,
797                    progress_callback: F,
798                    cancel_callback: C
799                )
800                    -> Result<(), String> {
801        FileExtImpl::copy_file_with_callbacks(from, to, block_size, progress_callback, cancel_callback)
802    }
803
804    /// Copies file block by block starting from specific byte. If block size is None it is set to 100kb.
805    /// Calls the progress callback at the beginning of the block copy.
806    /// Calls the cancel callback at the end of the block copy.
807    ///```
808    /// use file_ext::FileExt;
809    /// #[test]
810    /// fn copy_file_with_callback_and_block_size_starting_from_byte() {
811    ///     let block_size : u64 = 1000000;
812    ///     let pwd = FileExt::working_directory().unwrap();
813    ///     let mut label = "".to_string();
814    ///     let progress_callback = |start, end, total| { label = format!("copying block {}-{} of {} bytes", start, end, total).to_string(); };
815    ///     let cancel_callback = |_start, _end, _total| { false };
816    ///     let starting_byte = 4;
817    ///     FileExt::copy_file_with_callbacks_starting_from_byte(
818    ///         vec![pwd.as_str(), "LICENSE"],
819    ///         vec![pwd.as_str(), "LICENSE_copy4"],
820    ///         starting_byte,
821    ///         Some(block_size),
822    ///         progress_callback,
823    ///         cancel_callback
824    ///     ).unwrap();
825    ///
826    ///     let path = FileExt::build_path(vec![pwd.as_str(), "LICENSE_copy4"].as_slice());
827    ///     FileExt::delete_file(path.as_str()).unwrap();
828    /// }
829    ///```
830    pub fn copy_file_with_callbacks_starting_from_byte
831    <F: FnMut(u64, u64, u64), C: FnMut(u64, u64, u64) -> bool>
832    (
833        from: Vec<&str>,
834        to: Vec<&str>,
835        starting_byte: u64,
836        block_size: Option<u64>,
837        progress_callback: F,
838        cancel_callback: C,
839    )
840        -> Result<(), String> {
841        FileExtImpl::copy_file_with_callbacks_starting_from_byte(from, to, starting_byte, block_size, progress_callback, cancel_callback)
842    }
843
844    /// Copies file block by block starting from specific byte up to ending byte.
845    /// If block size is None it is set to 100kb.
846    /// Calls the progress callback at the beginning of the block copy.
847    /// Calls the cancel callback at the end of the block copy.
848    ///```
849    /// use file_ext::FileExt;
850    /// #[test]
851    /// fn copy_file_with_callback_and_block_size_starting_from_byte_to_ending_byte() {
852    ///     let block_size : u64 = 1000000;
853    ///     let pwd = FileExt::working_directory().unwrap();
854    ///     let mut label = "".to_string();
855    ///     let progress_callback = |start, end, total| { label = format!("copying block {}-{} of {} bytes", start, end, total).to_string(); };
856    ///     let cancel_callback = |_start, _end, _total| { false };
857    ///     let starting_byte = 4;
858    ///     let ending_byte = 10;
859    ///     FileExt::copy_file_with_callbacks_starting_from_byte_and_ending_at_byte(
860    ///         vec![pwd.as_str(), "LICENSE"],
861    ///         vec![pwd.as_str(), "LICENSE_copy5"],
862    ///         starting_byte,
863    ///         ending_byte,
864    ///         Some(block_size),
865    ///         progress_callback,
866    ///         cancel_callback
867    ///     ).unwrap();
868    ///
869    ///     let path = FileExt::build_path(vec![pwd.as_str(), "LICENSE_copy5"].as_slice());
870    ///     FileExt::delete_file(path.as_str()).unwrap();
871    /// }
872    ///```
873    pub fn copy_file_with_callbacks_starting_from_byte_and_ending_at_byte
874    <F: FnMut(u64, u64, u64), C: FnMut(u64, u64, u64) -> bool>
875    (
876        from: Vec<&str>,
877        to: Vec<&str>,
878        starting_byte: u64,
879        ending_byte: u64,
880        block_size: Option<u64>,
881        progress_callback: F,
882        cancel_callback: C,
883    )
884        -> Result<(), String>
885    {
886        FileExtImpl::copy_file_with_callbacks_starting_from_byte_and_ending_at_byte(from, to, starting_byte, ending_byte, block_size, progress_callback, cancel_callback)
887    }
888}
889