pobsd_db/
database.rs

1//! Provide a representation of the PlayOnBSD database than can be
2//! queried using a set of predefined methods.
3use 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/// Representation of the PlayOnBSD database that provides
42/// a set of methods to query and filter the games.
43#[derive(Default)]
44pub struct GameDataBase {
45    /// HashMap using the game uid as key and the corresponding game as value
46    pub(crate) games: HashMap<u32, Game>,
47    /// HashMap using the engine name as key and vector of game uid corresponding to said engine as value
48    pub(crate) engines: HashMap<String, Vec<u32>>,
49    /// HashMap using the runtime name as key and vector of game uid corresponding to said engine as value
50    pub(crate) runtimes: HashMap<String, Vec<u32>>,
51    /// HashMap using the genre name as key and vector of game uid corresponding to said engine as value
52    pub(crate) genres: HashMap<String, Vec<u32>>,
53    /// HashMap using the tag name as key and vector of game uid corresponding to said engine as value
54    pub(crate) tags: HashMap<String, Vec<u32>>,
55    /// HashMap using the year as key and vector of game uid corresponding to said engine as value
56    pub(crate) years: HashMap<String, Vec<u32>>,
57    /// HashMap using the dev name as key and vector of game uid corresponding to said engine as value
58    pub(crate) devs: HashMap<String, Vec<u32>>,
59    /// HashMap using the pub name as key and vector of game uid corresponding to said engine as value
60    pub(crate) publis: HashMap<String, Vec<u32>>,
61}
62
63impl GameDataBase {
64    /// Create a database for the given vector of games
65    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    /// Load the given game in the database
73    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}