use crate::error::Error;
use crate::package::PackageConfig;
use regex::{self, Regex};
use serde::Deserialize;
use std::fs::{self, File};
use std::io::Write;
pub type Platform = String;
pub type PackageID = String;
const CONFIG_PATH: &str = "Batch APK Installer";
const CONFIG_FILE: &str = "config.toml";
const CONFIG_TEMPLATE: &str = r#"directory = "/Users/user_name/Desktop"
platforms = [ "quest", "pico" ]
[[packages]]
id = "com.company.product.app"
platforms = [ "pico", "quest" ]
match_file_name = false
[[packages]]
id = "com.company.product.pico_only_app"
platforms = [ "pico" ]
match_file_name = true
[[packages]]
id = "com.company.product.quest_only_app"
platforms = [ "pico" ]
match_file_name = true"#;
#[derive(Deserialize)]
pub struct Config {
directory: String,
platforms: Vec<Platform>,
packages: Vec<PackageConfig>,
}
impl Config {
pub fn build() -> Result<Config, Error> {
let config_folder_path = dirs::config_dir().ok_or(Error::NoHomeDirectory)?;
let app_folder_path = config_folder_path.join(CONFIG_PATH);
let file_path = app_folder_path.join(CONFIG_FILE);
let Ok(config) = fs::read_to_string(&file_path) else {
if !fs::exists(&app_folder_path)? {
fs::create_dir_all(&app_folder_path)?;
}
let mut file = File::create(&file_path)?;
file.write_all(CONFIG_TEMPLATE.as_bytes())?;
let file_path = file_path.to_str().ok_or(Error::InvalidConfigPath)?;
println!("Config file not found. Created one at {file_path}. Modify it and try again");
return Err(Error::ConfigNotFound);
};
let config = toml::from_str(config.as_str())?;
Ok(config)
}
pub fn directory(&self) -> &str {
&self.directory
}
pub fn platforms(&self) -> &[Platform] {
&self.platforms
}
pub fn packages(&self) -> &[PackageConfig] {
&self.packages
}
}
pub fn parse_version(input: &str) -> Result<String, Error> {
let regex = Regex::new(r"\b\d+(\.\d+\b)+$")?;
let result = regex
.find(input)
.ok_or(Error::Parsing(String::from("Failed to parse version.")))?;
Ok(String::from(result.as_str()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_version_2_regions() {
assert_eq!(parse_version("5.1"), Ok("5.1".to_string()));
assert_eq!(parse_version("0.0"), Ok("0.0".to_string()));
assert_eq!(parse_version("0.1"), Ok("0.1".to_string()));
assert_eq!(parse_version("155.1"), Ok("155.1".to_string()));
assert_eq!(parse_version("5.999"), Ok("5.999".to_string()));
assert_eq!(parse_version("999.999"), Ok("999.999".to_string()));
}
#[test]
fn parse_version_3_regions() {
assert_eq!(parse_version("5.1.0"), Ok("5.1.0".to_string()));
assert_eq!(parse_version("0.0.0"), Ok("0.0.0".to_string()));
assert_eq!(parse_version("0.1.0"), Ok("0.1.0".to_string()));
assert_eq!(parse_version("1.155.1"), Ok("1.155.1".to_string()));
assert_eq!(parse_version("5.0.999"), Ok("5.0.999".to_string()));
assert_eq!(parse_version("999.999.999"), Ok("999.999.999".to_string()));
}
#[test]
fn parse_version_many_regions() {
assert_eq!(parse_version("5.1.1.1"), Ok("5.1.1.1".to_string()));
assert_eq!(parse_version("0.0.0.0.0.0"), Ok("0.0.0.0.0.0".to_string()));
assert_eq!(
parse_version("155.1.2.3.4.5"),
Ok("155.1.2.3.4.5".to_string())
);
assert_eq!(
parse_version("1.22.333.4444.55555.666666"),
Ok("1.22.333.4444.55555.666666".to_string())
);
}
#[test]
fn parse_invalid_version() {
assert!(parse_version("1").is_err());
assert!(parse_version("a").is_err());
assert!(parse_version("").is_err());
assert!(parse_version("1a").is_err());
assert!(parse_version("a1").is_err());
assert!(parse_version("aa").is_err());
assert!(parse_version("1.a").is_err());
assert!(parse_version("a.1").is_err());
assert!(parse_version("1.").is_err());
assert!(parse_version(".1").is_err());
assert!(parse_version("1.1a").is_err());
assert!(parse_version("1a.1").is_err());
assert!(parse_version("1. 0").is_err());
assert!(parse_version("1 .0").is_err());
assert!(parse_version("1.a.0").is_err());
assert!(parse_version("1.1.a").is_err());
}
}