improved some errors

This commit is contained in:
2026-03-02 23:13:00 +01:00
parent 53e4614970
commit 2c9206007f
4 changed files with 48 additions and 7 deletions

1
Cargo.lock generated
View File

@@ -305,6 +305,7 @@ dependencies = [
"log", "log",
"quick-xml", "quick-xml",
"serde", "serde",
"thiserror",
"toml", "toml",
] ]

View File

@@ -10,4 +10,5 @@ libloot = "0.29.0"
log = "0.4.29" log = "0.4.29"
quick-xml = { version = "0.39.2", features = ["serde-types", "serialize"] } quick-xml = { version = "0.39.2", features = ["serde-types", "serialize"] }
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
thiserror = "2.0.18"
toml = "1.0.3" toml = "1.0.3"

View File

@@ -2,9 +2,10 @@
// https://github.com/luctius/fomod/ // https://github.com/luctius/fomod/
// Original license: MIT / Apache-2.0 // Original license: MIT / Apache-2.0
use std::{error::Error, fs, path::Path}; use std::{fs, io, path::Path};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct Info { pub struct Info {
@@ -22,6 +23,15 @@ pub struct Info {
pub category_id: Option<usize>, pub category_id: Option<usize>,
} }
impl Info {
pub fn load_from_file(path: impl AsRef<Path>) -> Result<Self, FOModError> {
let data = fs::read_to_string(path)?;
let config = quick_xml::de::from_str(&data)?;
Ok(config)
}
}
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct Config { pub struct Config {
#[serde(rename = "moduleName")] #[serde(rename = "moduleName")]
@@ -44,7 +54,7 @@ pub struct Config {
} }
impl Config { impl Config {
pub fn load_from_file(path: impl AsRef<Path>) -> Result<Self, Box<dyn Error>> { pub fn load_from_file(path: impl AsRef<Path>) -> Result<Self, FOModError> {
let data = fs::read_to_string(path)?; let data = fs::read_to_string(path)?;
let config = quick_xml::de::from_str(&data)?; let config = quick_xml::de::from_str(&data)?;
@@ -52,6 +62,15 @@ impl Config {
} }
} }
#[derive(Error, Debug)]
pub enum FOModError {
#[error("Failed to read file")]
Io(#[from] io::Error),
#[error("Failed to parse config")]
Parse(#[from] quick_xml::de::DeError),
}
#[derive( #[derive(
Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash, Default,
)] )]

View File

@@ -1,10 +1,15 @@
use std::{ use std::{
error::Error, error::Error,
io,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use libloot::{Game, GameType}; use libloot::{
Game, GameType,
error::{GameHandleCreationError, LoadPluginsError, SortPluginsError},
};
use log::trace; use log::trace;
use thiserror::Error;
use crate::{ use crate::{
basic_types::{ModdedInstance, RootConfig}, basic_types::{ModdedInstance, RootConfig},
@@ -17,7 +22,7 @@ pub struct LoadOrder {
} }
impl LoadOrder { impl LoadOrder {
pub fn new(install_dir: impl AsRef<Path>, game_type: GameType) -> Result<Self, Box<dyn Error>> { pub fn new(install_dir: impl AsRef<Path>, game_type: GameType) -> Result<Self, LoadOrderError> {
Ok(Self { Ok(Self {
game: Game::with_local_path( game: Game::with_local_path(
game_type, game_type,
@@ -32,7 +37,7 @@ impl LoadOrder {
&mut self, &mut self,
root_config: &RootConfig, root_config: &RootConfig,
instance: &ModdedInstance, instance: &ModdedInstance,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), LoadOrderError> {
for installed_mod in &instance.mods { for installed_mod in &instance.mods {
let mod_config = root_config.get_mod_by_id(&installed_mod.mod_id()).unwrap(); let mod_config = root_config.get_mod_by_id(&installed_mod.mod_id()).unwrap();
let mod_source_root = root_config.get_mod_location(&mod_config); let mod_source_root = root_config.get_mod_location(&mod_config);
@@ -51,7 +56,7 @@ impl LoadOrder {
Ok(()) Ok(())
} }
pub fn add_plugins_from_install(&mut self) -> Result<(), Box<dyn Error>> { pub fn add_plugins_from_install(&mut self) -> Result<(), LoadOrderError> {
let plugins: Vec<_> = walk_files_recursive(self.target.join("Data"))? let plugins: Vec<_> = walk_files_recursive(self.target.join("Data"))?
.filter(|f| Self::is_plugin_file(f.path())) .filter(|f| Self::is_plugin_file(f.path()))
.map(|f| f.path()) .map(|f| f.path())
@@ -69,7 +74,7 @@ impl LoadOrder {
.is_some_and(|ext| ext == "esp" || ext == "esm" || ext == "esl") .is_some_and(|ext| ext == "esp" || ext == "esm" || ext == "esl")
} }
pub fn load_order(&self) -> Result<Vec<String>, Box<dyn Error>> { pub fn load_order(&self) -> Result<Vec<String>, LoadOrderError> {
trace!("Generating new load order"); trace!("Generating new load order");
let all_plugins = self.game.loaded_plugins(); let all_plugins = self.game.loaded_plugins();
let plugins_names: Vec<&str> = all_plugins.iter().map(|e| e.name()).collect(); let plugins_names: Vec<&str> = all_plugins.iter().map(|e| e.name()).collect();
@@ -79,3 +84,18 @@ impl LoadOrder {
Ok(sorted) Ok(sorted)
} }
} }
#[derive(Error, Debug)]
pub enum LoadOrderError {
#[error("Failed to read game directory")]
Io(#[from] io::Error),
#[error("Failed to create libloot game")]
Creating(#[from] GameHandleCreationError),
#[error("Failed to add plugins to libloot")]
Loading(#[from] LoadPluginsError),
#[error("libloot failed to sort plugins")]
Sorting(#[from] SortPluginsError),
}