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