cipherstash_config/
dataset.rs1use crate::{errors::ConfigError, list::UniqueList, TableConfig};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct DatasetConfig {
9 pub tables: UniqueList<TableConfig>,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct DatasetConfigWithIndexRootKey {
14 pub index_root_key: [u8; 32],
16 #[serde(flatten)]
17 pub config: DatasetConfig,
18}
19
20impl DatasetConfig {
21 pub fn init() -> Self {
22 Self {
23 tables: Default::default(),
24 }
25 }
26
27 pub fn add_table(mut self, config: TableConfig) -> Result<Self, ConfigError> {
28 self.tables.try_insert(config)?;
29
30 Ok(self)
31 }
32
33 pub fn has_table<Q>(&self, query: &Q) -> bool
35 where
36 TableConfig: PartialEq<Q>,
37 {
38 self.get_table(query).is_some()
39 }
40
41 pub fn get_table<Q>(&self, query: &Q) -> Option<&TableConfig>
43 where
44 TableConfig: PartialEq<Q>,
45 {
46 self.tables.get(query)
47 }
48
49 pub fn sort_indexes_by_type(mut self) -> Self {
55 self.tables
56 .iter_mut()
57 .for_each(TableConfig::sort_indexes_by_type);
58
59 self
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use indoc::indoc;
67 use std::error::Error;
68 use toml::to_string_pretty;
69
70 use crate::*;
71
72 #[test]
73 fn add_and_get_table() -> Result<(), Box<dyn Error>> {
74 let config = DatasetConfig::init().add_table(TableConfig::new("users")?)?;
75
76 assert!(matches!(
77 config.get_table(&"users"),
78 Some(TableConfig { path, .. }) if path.as_string() == "users"
79 ));
80
81 Ok(())
82 }
83
84 #[test]
85 fn add_and_get_table_with_schema() -> Result<(), Box<dyn Error>> {
86 let config = DatasetConfig::init().add_table(TableConfig::new("public.users")?)?;
87
88 assert!(matches!(
89 config.get_table(&"users"),
90 Some(TableConfig { path, .. }) if path.as_string() == "public.users"
91 ));
92
93 Ok(())
94 }
95
96 #[test]
97 fn test_serialise_to_toml_single_table() -> Result<(), Box<dyn Error>> {
98 let config = DatasetConfig::init().add_table(TableConfig::new("test")?)?;
99
100 assert_eq!(
101 to_string_pretty(&config)?,
102 indoc! { r#"
103 [[tables]]
104 path = "test"
105 fields = []
106 "#}
107 );
108
109 Ok(())
110 }
111
112 #[test]
113 fn test_serialise_to_toml_multiple_table() -> Result<(), Box<dyn Error>> {
114 let config = DatasetConfig::init()
115 .add_table(TableConfig::new("test")?)?
116 .add_table(
117 TableConfig::new("another")?.add_column(
118 ColumnConfig::build("great-column")
119 .add_index(column::Index::new_ore())
120 .add_index(column::Index::new_match()),
121 )?,
122 )?;
123
124 assert_eq!(
125 to_string_pretty(&config)?,
126 indoc! { r#"
127 [[tables]]
128 path = "test"
129 fields = []
130
131 [[tables]]
132 path = "another"
133
134 [[tables.fields]]
135 name = "great-column"
136 in_place = false
137 cast_type = "utf8-str"
138 mode = "encrypted-duplicate"
139
140 [[tables.fields.indexes]]
141 version = 1
142 kind = "ore"
143
144 [[tables.fields.indexes]]
145 version = 1
146 kind = "match"
147 k = 6
148 m = 2048
149 include_original = true
150
151 [tables.fields.indexes.tokenizer]
152 kind = "ngram"
153 token_length = 3
154
155 [[tables.fields.indexes.token_filters]]
156 kind = "downcase"
157 "#}
158 );
159
160 Ok(())
161 }
162
163 #[test]
164 fn test_sort_indexes() -> Result<(), Box<dyn Error>> {
165 let config = DatasetConfig::init()
166 .add_table(
167 TableConfig::new("users")?.add_column(
168 ColumnConfig::build("name")
169 .add_index(column::Index::new_ore())
170 .add_index(column::Index::new_unique())
171 .add_index(column::Index::new_match()),
172 )?,
173 )?
174 .sort_indexes_by_type();
175
176 let index_types = &config.tables[0].fields[0]
177 .indexes
178 .iter()
179 .map(|index| index.as_str())
180 .collect::<Vec<_>>();
181
182 assert_eq!(index_types, &vec!["match", "ore", "unique"]);
183
184 Ok(())
185 }
186}