1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::path::PathBuf;

pub struct ModList {
    pub mods: Vec<Mod>,
}

impl ModList {
    pub fn new() -> ModList {
        ModList { mods: Vec::new() }
    }

    pub fn add_mod(&mut self, mod_: Mod) {
        self.mods.push(mod_);
    }

    pub fn add_mod_from_path(&mut self, path: &PathBuf) -> std::io::Result<()> {
        let mod_ = Mod::new_from_path(path)?;
        self.add_mod(mod_);
        Ok(())
    }

    pub fn add_mods_from_dir(&mut self, dir: &PathBuf) -> std::io::Result<()> {
        let mut entries = std::fs::read_dir(dir)?
            .map(|res| res.map(|e| e.path()))
            .collect::<Result<Vec<_>, std::io::Error>>()?;

        entries.sort();

        for entry in entries {
            let as_path = entry.as_path();
            if as_path.is_file() {
                self.add_mod_from_path(&entry.to_path_buf())?;
            }
        }
        Ok(())
    }
}

impl Default for ModList {
    fn default() -> Self {
        ModList::new()
    }
}

pub struct Mod {
    pub name: String,
    pub path: String,
    pub version: String,
    pub supported_version: String,
    pub remote_file_id: String,
}

impl Default for Mod {
    fn default() -> Self {
        Mod::new(
            String::from(""),
            String::from(""),
            String::from(""),
            String::from(""),
            String::from(""),
        )
    }
}

impl Mod {
    pub fn new_from_path(path: &PathBuf) -> std::io::Result<Mod> {
        let content = std::fs::read_to_string(path)?;
        Mod::new_from_file_content(&content)
    }

    fn new_from_file_content(content: &str) -> std::io::Result<Mod> {
        mod_from_file_content(content)
    }

    fn new(
        name: String,
        path: String,
        version: String,
        supported_version: String,
        remote_file_id: String,
    ) -> Mod {
        Mod {
            name,
            path,
            version,
            supported_version,
            remote_file_id,
        }
    }
}

pub fn mod_from_file_content(content: &str) -> std::io::Result<Mod> {
    let mut name = String::from("");
    let mut path = String::from("");
    let mut version = String::from("");
    let mut supported_version = String::from("");
    let mut remote_file_id = String::from("");

    for line in content.lines() {
        let mut parts = line.split('=');
        let key = parts.next().unwrap_or("");
        let value = parts.next().unwrap_or("").trim_matches('"');

        match key {
            "name" => name = String::from(value),
            "path" => path = String::from(value),
            "version" => version = String::from(value),
            "supported_version" => supported_version = String::from(value),
            "remote_file_id" => remote_file_id = String::from(value),
            _ => (),
        }
    }

    Ok(Mod::new(
        name,
        path,
        version,
        supported_version,
        remote_file_id,
    ))
}