use crate::models::Game;
use paste::paste;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
macro_rules! load_game {
(items: $($item:ident),+; arrays: $($array:ident),+) => {
paste! {
pub fn load_game(&mut self, game: Game) {
let uid = game.uid;
self.add_game(game);
let game = self.games.get(&uid).unwrap().clone();
$(
if let Some(item) = &game.$item {
self.[<add_game_to_ $item s>](&item, game.uid);
}
)*
$(
if let Some(items) = &game.$array {
for item in items {
self.[<add_game_to_ $array>](&item, game.uid);
}
}
)*
}
}
};
}
macro_rules! add_game_to {
($field:ident) => {
paste! {
fn [<add_game_to_ $field>](&mut self, item: &str, game_id: u32) {
match self.[<$field>].get_mut(item) {
Some(item) => item.push(game_id),
None => {
let _ = self.[<$field>].insert(item.into(), vec![game_id]);
}
}
}
}
};
}
#[derive(Default, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct GameDataBase {
pub(crate) games: HashMap<u32, Game>,
pub(crate) engines: HashMap<String, Vec<u32>>,
pub(crate) runtimes: HashMap<String, Vec<u32>>,
pub(crate) genres: HashMap<String, Vec<u32>>,
pub(crate) tags: HashMap<String, Vec<u32>>,
pub(crate) years: HashMap<String, Vec<u32>>,
pub(crate) devs: HashMap<String, Vec<u32>>,
pub(crate) publis: HashMap<String, Vec<u32>>,
}
impl GameDataBase {
pub fn new(games: Vec<Game>) -> Self {
let mut db = GameDataBase::default();
for game in games {
db.load_game(game);
}
db
}
load_game!(
items: engine, runtime, year;
arrays: devs, publis, genres, tags
);
fn add_game(&mut self, game: Game) {
self.games.insert(game.uid, game);
}
add_game_to!(tags);
add_game_to!(engines);
add_game_to!(runtimes);
add_game_to!(genres);
add_game_to!(years);
add_game_to!(devs);
add_game_to!(publis);
}