1use paste::paste;
4use pobsd_parser::Game;
5use std::collections::HashMap;
6
7macro_rules! add_game_to {
8 ($field:ident) => {
9 paste! {
10 fn [<add_game_to_ $field>](&mut self, item: &str, game_id: u32) {
11 match self.[<$field>].get_mut(item) {
12 Some(item) => item.push(game_id),
13 None => {
14 let _ = self.[<$field>].insert(item.into(), vec![game_id]);
15 }
16 }
17 }
18 }
19 };
20}
21
22macro_rules! push {
23 ($game:ident, $field:ident, $db:ident ) => {
24 paste! {
25 if let Some(item) = &$game.$field {
26 $db.[<add_game_to_ $field s>](&item, $game.uid);
27 }
28 }
29 };
30 ($game:ident, array $field:ident, $db:ident) => {
31 paste! {
32 if let Some(items) = &$game.$field {
33 for item in items {
34 $db.[<add_game_to_ $field>](&item, $game.uid);
35 }
36 }
37 }
38 };
39}
40
41#[derive(Default)]
44pub struct GameDataBase {
45 pub(crate) games: HashMap<u32, Game>,
47 pub(crate) engines: HashMap<String, Vec<u32>>,
49 pub(crate) runtimes: HashMap<String, Vec<u32>>,
51 pub(crate) genres: HashMap<String, Vec<u32>>,
53 pub(crate) tags: HashMap<String, Vec<u32>>,
55 pub(crate) years: HashMap<String, Vec<u32>>,
57 pub(crate) devs: HashMap<String, Vec<u32>>,
59 pub(crate) publis: HashMap<String, Vec<u32>>,
61}
62
63impl GameDataBase {
64 pub fn new(games: Vec<Game>) -> Self {
66 let mut db = GameDataBase::default();
67 for game in games {
68 db.load_game(game);
69 }
70 db
71 }
72 pub fn load_game(&mut self, game: Game) {
74 let uid = game.uid;
75 self.add_game(game);
76 let game = self.games.get(&uid).unwrap().clone();
77
78 push!(game, engine, self);
79 push!(game, runtime, self);
80 push!(game, array genres, self);
81 push!(game, array tags, self);
82 push!(game, year, self);
83 push!(game, dev, self);
84 push!(game, publi, self);
85 }
86 fn add_game(&mut self, game: Game) {
87 self.games.insert(game.uid, game);
88 }
89 add_game_to!(tags);
90 add_game_to!(engines);
91 add_game_to!(runtimes);
92 add_game_to!(genres);
93 add_game_to!(years);
94 add_game_to!(devs);
95 add_game_to!(publis);
96}