diamondfire_actiondump/
registry.rs

1//! An interface for loading and accessing a full action dump.
2
3use crate::schema::CodeData;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7type DatabaseValues = HashMap<String, CodeRegistry>;
8
9
10/// A full code database which can be used to load an action dump.
11#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
12pub struct CodeDatabase {
13    /// The code database values.
14    #[serde(flatten)]
15    pub values: DatabaseValues,
16}
17
18impl CodeDatabase {
19    /// Create a new code database from its values.
20    pub fn new(values: DatabaseValues) -> Self {
21        CodeDatabase {
22            values
23        }
24    }
25}
26
27impl From<CodeDatabase> for DatabaseValues {
28    fn from(database: CodeDatabase) -> Self {
29        database.values
30    }
31}
32
33/// A registry holding a [`Vec<CodeData>`] and indexes from names and values.
34#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
35#[serde(from = "Vec<CodeData>", into = "Vec<CodeData>")]
36pub struct CodeRegistry {
37    /// A list of all the items in this registry.
38    pub items: Vec<CodeData>,
39    /// A mapping from name to index for all [`CodeData`] elements where it is present.
40    by_name: HashMap<String, usize>,
41    /// A mapping from identifier to index for all [`CodeData`] elements where it is present.
42    by_id: HashMap<String, usize>,
43}
44
45impl CodeRegistry {
46    /// Create a [`CodeRegistry`] from a [`Vec<CodeData>`].
47    ///
48    /// This will iterate over the list of items at least 2 times.
49    pub fn new(items: Vec<CodeData>) -> Self {
50        let by_name = items
51            .iter()
52            .enumerate()
53            .filter_map(|(i, v)| v.name.to_owned().map(|k| (k, i)))
54            .collect();
55        let by_id = items
56            .iter()
57            .enumerate()
58            .filter_map(|(i, v)| v.identifier.to_owned().map(|k| (k, i)))
59            .collect();
60
61        CodeRegistry {
62            items,
63            by_name,
64            by_id,
65        }
66    }
67
68    /// Fetch a [`CodeData`] element by its `name`.
69    pub fn get_by_name(&self, name: String) -> Option<&CodeData> {
70        self.items.get(self.by_name.get(&name)?.to_owned())
71    }
72
73    /// Fetch a [`CodeData`] element by its `identifier`.
74    pub fn get_by_id(&self, id: String) -> Option<&CodeData> {
75        self.items.get(self.by_id.get(&id)?.to_owned())
76    }
77}
78
79impl From<Vec<CodeData>> for CodeRegistry {
80    fn from(internal: Vec<CodeData>) -> Self {
81        CodeRegistry::new(internal)
82    }
83}
84
85impl From<CodeRegistry> for Vec<CodeData> {
86    fn from(registry: CodeRegistry) -> Self {
87        registry.items
88    }
89}