use serde::de::DeserializeOwned; use std::collections::HashMap; use super::GamesPlatform; use crate::settings::load_setting_sections; const PLATFORM_NAMES: [&str; 14] = [ "amazon", "bottles", "epic_games", "flatpak", "gog", "heroic", "itch", "legendary", "lutris", "origin", "uplay", "minigalaxy", "playnite", "gamepass" ]; pub type Platforms = Vec>; pub fn load_platform, B: AsRef>( name: A, settings_string: B, ) -> eyre::Result> { let name = name.as_ref(); let s = settings_string.as_ref(); #[cfg(not(target_family = "unix"))] { //Windows only platforms use super::amazon::AmazonPlatform; use super::playnite::PlaynitePlatform; use super::gamepass::GamePassPlatForm; match name { "amazon" => return load::(s), "playnite" => return load::(s), "gamepass" => return load::(s), _ => {} } } #[cfg(target_family = "unix")] { use super::bottles::BottlesPlatform; use super::flatpak::FlatpakPlatform; use super::heroic::HeroicPlatform; use super::legendary::LegendaryPlatform; use super::lutris::LutrisPlatform; use super::minigalaxy::MiniGalaxyPlatform; //Linux only platforms match name { "bottles" => return load::(s), "flatpak" => return load::(s), "minigalaxy" => return load::(s), "legendary" => return load::(s), "lutris" => return load::(s), "heroic" => return load::(s), _ => {} } } //Common platforms use super::egs::EpicPlatform; use super::gog::GogPlatform; use super::itch::ItchPlatform; use super::origin::OriginPlatform; use super::uplay::UplayPlatform; match name { "epic_games" => load::(s), "uplay" => load::(s), "itch" => load::(s), "gog" => load::(s), "origin" => load::(s), _ => Err(eyre::format_err!("Unknown platform named {name}")), } } pub fn get_platforms() -> Platforms { let sections = load_setting_sections(); let sections = match sections { Ok(s) => s, Err(err) => { eprintln!( "Could not load platform settings, using defaults: Error: {err:?}" ); HashMap::new() } }; let mut platforms = vec![]; for name in PLATFORM_NAMES { let default = String::from(""); let settings = sections.get(name).unwrap_or(&default); match load_platform(name, settings) { Ok(platform) => platforms.push(platform), Err(e) => eprintln!("Could not load platform {name}, gave error: {e}"), } } platforms } pub fn load_settings>(input: S) -> Setting where Setting: Default, Setting: DeserializeOwned, { let str = input.as_ref(); match toml::from_str(str) { Ok(k) => k, Err(err) => { if !str.is_empty() { eprintln!("Error reading settings file {err:?}"); } Setting::default() } } } fn load(s: &str) -> eyre::Result> where T: FromSettingsString, T: GamesPlatform, T: 'static, { Ok(Box::new(T::from_settings_string(s))) } pub trait FromSettingsString { fn from_settings_string>(s: S) -> Self; }