use anyhow::{Context, Result};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{fmt::Display, fs, str::FromStr};
use super::FILE_NAME;
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
pub(crate) struct Index {
pub(crate) mods: Vec<Mod>,
}
impl Index {
pub fn read() -> Result<Self> {
let p = std::env::current_dir()?.join(FILE_NAME);
if let Ok(raw) = fs::read_to_string(&p) {
ron::from_str(&raw).context("Unable to parse index")
} else {
Ok(Index::default())
}
}
pub fn write(&self) -> Result<()> {
let cfg = ron::ser::PrettyConfig::new().compact_arrays(true);
let p = std::env::current_dir()?.join(FILE_NAME);
let raw = ron::ser::to_string_pretty(self, cfg)?;
fs::write(&p, &raw).context("Failed to write index")?;
Ok(())
}
}
#[derive(Deserialize, Serialize, Debug, Clone)]
pub(crate) struct Mod {
name: String,
author: String,
version: Version,
}
impl Mod {
pub(crate) fn new(author: String, name: String, version: String) -> Self {
Mod {
author,
name,
version: version.parse::<Version>().unwrap(),
}
}
}
#[derive(Deserialize, Serialize, Debug, Clone)]
struct Version {
major: u8,
minor: u8,
patch: u8,
}
impl FromStr for Version {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let re = Regex::new(r"(\d+)\.(\d+)\.(\d+)").unwrap();
if let Some(c) = re.captures(s) {
let major = c.get(1).unwrap().as_str().parse::<u8>().unwrap();
let minor = c.get(2).unwrap().as_str().parse::<u8>().unwrap();
let patch = c.get(3).unwrap().as_str().parse::<u8>().unwrap();
Ok(Version {
major,
minor,
patch,
})
} else {
Err(String::from("Unable to parse version"))
}
}
}
impl Display for Version {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
}
}