fileman_rs/
lib.rs

1#![crate_name = "fileman_rs"]
2//! A high-performance file management system for working with large quantities of files written in Rust.
3
4// declare cargo crates
5use std::io;
6
7// declare local modules
8mod organize;
9mod tools;
10
11pub trait RunTask {
12    /// task definition that allows Config to run a task outlined in a task module
13    ///
14    /// # Arguments
15    ///
16    /// `&self` - a reference to Config enum
17    fn run_task(&self) -> Result<(), io::Error>;
18}
19
20#[derive(Debug, PartialEq, Eq)]
21pub enum Config {
22    /// configuration enum, all tasks are given their own variant
23    // variant to run the organize task
24    Organize(organize::OrganizeTask),
25}
26
27impl Config {
28    /// Config enum constructor
29    ///
30    /// # Arguments
31    ///
32    /// `args` - an iterator containing Strings to be used as arguments
33    ///
34    /// # Errors
35    ///
36    /// - no task specified
37    /// - provided task does not match any defined task
38    /// - error propagated upward from subsequent function calls
39    pub fn new(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {
40        //skips the path to the compiled file (first argument passed in)
41        args.next();
42
43        // errors if there is no task specified
44        let task = match args.next() {
45            Some(arg) => arg,
46            None => return Err("no task specified"),
47        };
48
49        // match an all lowercase task to a set of predefined tasks
50        match task.to_lowercase().as_str() {
51            "organize" => {
52                // ensures OrganizeTask created successfully, otherwise propagates error
53                let organize_task = organize::OrganizeTask::new(args)?;
54
55                Ok(Self::Organize(organize_task))
56            }
57            // errors if desired task is not defined
58            _ => return Err("provided task did not match any defined tasks"),
59        }
60    }
61}
62
63/// RunTask trait allows for all tasks to be run from main.rs
64impl RunTask for Config {
65    /// run_task() matches against Config and runs the corresponding method Variant(task) => task.run_task()
66    /// 
67    /// # Arguments
68    /// 
69    /// `&self` reference to Config enum
70    /// 
71    /// # Errors
72    /// 
73    /// - if Variant(task) => task.run_task() errors
74    fn run_task(&self) -> Result<(), io::Error> {
75        match self {
76            Config::Organize(task) => task.run_task(),
77        }
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    /// verifies Config::new() works correctly with valid arguments passed in
86    ///
87    /// # Arguments
88    ///
89    /// None
90    ///
91    /// # Errors
92    ///
93    /// - Config::new() doesnt error if args does not contain a task
94    #[test]
95    fn config_new_organize_with_valid_args() {
96        // args iterator
97        let args_1 = [String::from("./src"), String::from("./src/organize")].into_iter();
98
99        let organize_task = organize::OrganizeTask::new(args_1).unwrap();
100
101        // args iterator
102        let args_2 = [
103            String::from("foo"),
104            String::from("organize"),
105            String::from("./src"),
106            String::from("./src/organize"),
107        ]
108        .into_iter();
109
110        assert_eq!(Config::new(args_2), Ok(Config::Organize(organize_task)))
111    }
112
113    /// verifies Config::new() errors if args does contain a task
114    ///
115    /// # Arguments
116    ///
117    /// None
118    ///
119    /// # Errors
120    ///
121    /// - Config::new() doesnt error if args does not contain a task
122    #[test]
123    fn config_new_no_task() {
124        // args iterator
125        let args = [String::from("foo")].into_iter();
126
127        assert!(Config::new(args).is_err());
128    }
129
130    /// verifies Config::new() errors if an invalid task is requested
131    ///
132    /// # Arguments
133    ///
134    /// None
135    ///
136    /// # Errors
137    ///
138    /// - Config::new() doesnt error if an undefined task is requested
139    #[test]
140    fn config_new_invalid_task() {
141        // args iterator
142        let args = [String::from("foo"), String::from("bar")].into_iter();
143        assert!(Config::new(args).is_err());
144    }
145}