flashpoint_archive/game/
ext.rs

1use std::collections::HashMap;
2
3use crate::error::{self, Result};
4use rusqlite::Connection;
5use snafu::ResultExt;
6
7#[cfg_attr(feature = "napi", napi(object))]
8pub struct ExtensionIndex {
9    pub name: String,
10    pub key: String,
11}
12
13#[cfg_attr(feature = "napi", napi)]
14#[cfg_attr(not(feature = "napi"), derive(Clone))]
15#[derive(PartialEq)]
16pub enum ExtSearchableType {
17    String,
18    Boolean,
19    Number,
20}
21
22#[cfg_attr(feature = "napi", napi(object))]
23pub struct ExtSearchable {
24    pub key: String,
25    pub value_type: ExtSearchableType,
26    pub search_key: String,
27}
28
29pub struct ExtSearchableRegistered {
30    pub ext_id: String,
31    pub key: String,
32    pub value_type: ExtSearchableType,
33}
34
35#[cfg_attr(feature = "napi", napi(object))]
36pub struct ExtensionInfo {
37    pub id: String,
38    pub searchables: Vec<ExtSearchable>,
39    pub indexes: Vec<ExtensionIndex>,
40}
41
42pub struct ExtensionRegistry {
43    extensions: HashMap<String, ExtensionInfo>,
44    pub searchables: HashMap<String, ExtSearchableRegistered>,
45}
46
47impl Default for ExtensionRegistry {
48    fn default() -> Self {
49        ExtensionRegistry {
50            extensions: HashMap::new(),
51            searchables: HashMap::new(),
52        }
53    }
54}
55
56impl ExtensionRegistry {
57    pub fn new() -> Self {
58        ExtensionRegistry::default()
59    }
60
61    pub fn register(&mut self, conn: &Connection, ext: ExtensionInfo) -> Result<()> {
62        // Create relevant indices if missing
63        self.create_indexes(conn, &ext)
64            .context(error::SqliteSnafu)?;
65
66        // Insert to registry
67        for searchable in &ext.searchables {
68            self.searchables.insert(searchable.search_key.clone(), ExtSearchableRegistered {
69                ext_id: ext.id.clone(),
70                key: searchable.key.clone(),
71                value_type: searchable.value_type.clone()
72            });
73        }
74        self.extensions.insert(ext.id.clone(), ext);
75
76        Ok(())
77    }
78
79    fn create_indexes(&self, conn: &Connection, ext: &ExtensionInfo) -> rusqlite::Result<()> {
80        // Create each new index
81        for index in &ext.indexes {
82            let index_name = format!("idx_ext_{}_{}", ext.id, index.name);
83
84            let stmt = format!(
85                "CREATE INDEX IF NOT EXISTS {} on ext_data(extId, JSON_EXTRACT(data, '$.{}'))",
86                index_name, index.key
87            );
88
89            conn.execute(&stmt, [])?;
90        }
91
92        // TODO: Remove unused indicies
93
94        Ok(())
95    }
96}