Language Migration (#21)

* Blank slate

* Added gitignore

* Updated gitignore

* Added rust code

* Added modules

* Fixed build issues

* rustfmt

* Updated models

* Added parsers module

* Updated utilities module

* Updated main.rs

* Updated api_parser and song model

* Updated icarus_action model

* Updated structs in managers module

* Updated main.rs

* More changes

* Saving changes

* Added new struct and methods

* More changes. Not functional yet

* Changed name of the project

* Removed cmake workflow

* Adding rust workflow

* Adding code to the syncers module

* Cargo formatting

* Continuing work

* Adding code to the syncers module

* Added dependencies

* Adding more code to the syncers module

* Added more code to the syncers module

It's not 100 percent done yet, I'll work on other modules

* Added more code to the managers module

* Added code to request a token

* Cargo formatting

* Adding more code to multi target upload

* Adding more multi-target upload code and formatted code

* Added more multi-upload code

* cargo fmt

* Got uploading functional and cargo fmt-ing

* Uploading multi target works, but is buggy

Not all of the songs are being uploaded

* Added single target upload

* Single target upload is functional but need to revisit multi-target upload

Multi-target upload is broken now. Needs to be revisited

* Fixed multi target upload

* Can now retrieve songs

* Downloading functionality is working

* Delete functionality is operational

* Updated README

* More cleanup

* Added test
This commit was merged in pull request #21.
This commit is contained in:
Kun Deng
2024-06-15 12:22:17 -04:00
committed by GitHub
parent 5e9e7bc46a
commit ee4469b385
79 changed files with 2148 additions and 3376 deletions
+221
View File
@@ -0,0 +1,221 @@
use serde::{Deserialize, Serialize};
use crate::models;
#[derive(Debug, Deserialize, Serialize)]
pub struct ActionManager {
pub action: String,
pub flags: Vec<models::flags::Flags>,
pub params: Vec<String>,
pub param_count: i32,
}
impl ActionManager {
pub fn retrieve_icarus_action(&self) -> models::icarus_action::IcarusAction {
return models::icarus_action::IcarusAction {
flags: self.flags.clone(),
action: String::from(&self.action),
};
}
fn supported_flags(&self) -> Vec<String> {
return vec![
String::from("-u"),
String::from("-p"),
String::from("-t"),
String::from("-h"),
String::from("-s"),
String::from("-sd"),
String::from("-sr"),
String::from("-d"),
String::from("-D"),
String::from("-b"),
String::from("-rt"),
String::from("-nc"),
String::from("-m"),
String::from("-ca"),
String::from("-smca"),
String::from("-t"),
];
}
pub fn initialize(&mut self) {
self.validate_flags();
self.validate_action();
self.action = self.action.to_lowercase();
}
fn validate_flags(&mut self) {
println!("Validating flags");
let flag_vals = self.parsed_flags();
let mut i = 0;
println!("Flag count: {}", flag_vals.len());
while i < flag_vals.len() {
let flag = &flag_vals[i];
println!("Index: {} | Value: {}", i, flag);
let mut flg = models::flags::Flags::default();
if self.is_valid_flag(flag) && self.does_flag_have_value(flag) {
println!("Flag has value");
flg.flag = String::from(flag);
flg.value = String::from(&flag_vals[i + 1]);
i = i + 1;
} else if self.is_valid_flag(flag) {
println!("Flag does not have a value");
flg.flag = String::from(flag);
} else {
println!("Flag {} is not valid", flag);
std::process::exit(-1);
}
self.flags.push(flg);
println!("");
i += 1;
}
}
fn validate_action(&mut self) {
if self.params.len() >= 2 {
let act = &self.params[1];
self.action = String::from(act);
}
}
fn is_valid_flag(&self, flag: &String) -> bool {
let flags = self.supported_flags();
let mut found: bool = false;
for flg in &flags {
if flg == flag {
found = true;
break;
}
}
return found;
}
fn does_flag_have_value(&self, flag: &String) -> bool {
let flags_tmp = self.parsed_flags();
let mut i_found: i32 = -1;
for i in 0..flags_tmp.len() {
let flg = &flags_tmp[i];
if flg == flag {
i_found = i as i32;
break;
}
}
if i_found >= 0 {
if (i_found + 1) < flags_tmp.len().try_into().unwrap() {
return true;
} else {
return false;
}
} else {
return false;
}
}
fn _print_action(&self) {
if self.action.len() == 0 {
println!("Action is empty");
} else {
println!("Action is {}", self.action);
}
}
fn _print_flags(&self) {
println!("Printing flags...");
for flag in &self.flags {
println!("Flag {}", flag.flag);
println!("Value {}", flag.value);
}
}
fn parsed_flags(&self) -> Vec<String> {
let mut parsed: Vec<String> = Vec::new();
for i in 2..self.params.len() {
let flag = String::from(&self.params[i]);
parsed.push(flag);
}
return parsed;
}
}
#[cfg(test)]
mod tests {
use crate::managers::action_managers::ActionManager;
#[test]
fn minimum_action_and_args() {
let args: Vec<String> = vec![
"icarus-dm".to_string(),
"download".to_string(),
"-u".to_string(),
"jamborie".to_string(),
"-p".to_string(),
"somethingsecr3t!".to_string(),
"-h".to_string(),
"https://music-server.com".to_string(),
];
let arg_count = args.len() as i32;
let minimum_arg_count = 8;
assert!(arg_count >= minimum_arg_count);
let mut act_mgr = ActionManager {
action: String::new(),
flags: Vec::new(),
params: args,
param_count: arg_count,
};
act_mgr.initialize();
let ica = act_mgr.retrieve_icarus_action();
let action = &ica.action;
let flags = &ica.flags;
assert!(action != "");
assert!(flags.len() > 2);
assert!(
!(action != "download"
&& action != "upload"
&& action != "retrieve"
&& action != "upload-meta")
);
let mut all_flags_found = false;
let mut found_count = 0;
let mut flags_already_read = Vec::new();
for flag in flags {
if flags_already_read.contains(&flag.flag) {
continue;
}
if flag.flag == "-u" {
found_count += 1;
flags_already_read.push(flag.flag.clone());
} else if flag.flag == "-p" {
found_count += 1;
flags_already_read.push(flag.flag.clone());
} else if flag.flag == "-h" {
found_count += 1;
flags_already_read.push(flag.flag.clone());
}
}
all_flags_found = found_count == 3;
assert_eq!(found_count, 3, "Three flags are required: -u, -p, -h");
assert!(all_flags_found, "All flags have not been found");
}
}