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}