qserve 1.2.0

Quickly serve your files on your network with speed and simplicity.
use std::{env, fs, path::Path, path::PathBuf, process::exit};

#[derive(Debug)]
pub struct Config {
    pub ip: String,
    pub port: String,
    pub chunks: usize,
    pub path: String,
    pub preview: String,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            ip: "0.0.0.0".to_string(),
            port: "3000".to_string(),
            chunks: 4096,
            path: ".".to_string(),
            preview: "None".to_string(),
        }
    }
}

impl Config {
    fn parse_args(args: &[String], long_arg: &str, short_arg: &str, default: String) -> String {
        let mut value = String::from(default);

        for (index, arg) in args.iter().enumerate() {
            match arg.as_str() {
                arg if arg == short_arg || arg == long_arg => {
                    value = args.get(index + 1).cloned().unwrap_or_default();
                }

                _ => {}
            }
        }

        value
    }

    pub fn parse() -> Self {
        let config = Config::default();
        let args: Vec<String> = env::args().collect();
        let path = Self::parse_args(&args, "--path", "-P", ".".to_string());
        let mut config_path = fs::canonicalize(path);
        let version = env!("CARGO_PKG_VERSION");
        if Self::parse_args(&args, "--version", "-v", "None".to_string()) != "None" {
            println!("qserve {}", version);
            exit(0);
        }
        if Self::parse_args(&args, "--help", "-h", "None".to_string()) != "None" {
            let message = format!(
                "Qserve - {0}\n
            --ip      or -i – to set the ip address	[default: 0.0.0.0]
            --port    or -p – to set the port		[default: 3000]
            --path    or -P – to set the path to serve	[default: . (current dir)]
            --chunks  or -c – to set chunk size 	[default: 4096]
            --version or -v – print version and exit
            --help    or -h – print this message and exit 
            ",
                version
            );

            println!("{}", message);
            exit(0);
        }

        let mut preview_file = String::from("None");
        let mut dir_path = config_path.as_mut().unwrap().display().to_string();
        if fs::metadata(config_path.as_mut().unwrap())
            .unwrap()
            .is_file()
        {
            preview_file = config_path.as_mut().unwrap().display().to_string();
            dir_path = Path::new(&preview_file)
                .parent()
                .unwrap()
                .display()
                .to_string()
        }
        Config {
            ip: Self::parse_args(&args, "--ip", "-i", config.ip),
            port: Self::parse_args(&args, "--port", "-p", config.port),
            chunks: Self::parse_args(&args, "--chunks", "-c", config.chunks.to_string())
                .parse()
                .unwrap(),
            path: dir_path,
            preview: preview_file,
        }
    }
}

pub fn get_short_path(mut req_path: String) -> String {
    let config = Config::parse();

    if !req_path.starts_with('/') {
        let formatted_path = format!("/{}", req_path);
        req_path = formatted_path
    }
    let mut absolute_path = Path::new(&req_path)
        .to_str()
        .unwrap()
        .replacen(&config.path, "", 1);

    if absolute_path == "/." {
        absolute_path = "./".to_string()
    }

    absolute_path
}

pub fn get_full_path(short_path: String) -> String {
    let config = Config::parse();
    let short_path = short_path.replacen('/', "", 1);
    PathBuf::from(config.path)
        .join(short_path)
        .display()
        .to_string()
}