cipherstash_config/table/
config.rs

1use crate::errors::ConfigError;
2use crate::list::{ListEntry, UniqueList};
3use crate::ColumnConfig;
4use std::fmt::Debug;
5
6use super::TablePath;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct TableConfig {
11    pub path: TablePath,
12    pub fields: UniqueList<ColumnConfig>,
13}
14
15impl ListEntry for TableConfig {}
16
17impl PartialEq for TableConfig {
18    fn eq(&self, other: &Self) -> bool {
19        self.path == other.path
20    }
21}
22
23impl PartialEq<TablePath> for TableConfig {
24    fn eq(&self, other: &TablePath) -> bool {
25        self.path == *other
26    }
27}
28
29impl PartialEq<&str> for TableConfig {
30    fn eq(&self, other: &&str) -> bool {
31        match TablePath::try_from(*other) {
32            Ok(path) => self.path == path,
33            Err(_) => false,
34        }
35    }
36}
37
38impl TableConfig {
39    pub fn new<R>(path: R) -> Result<Self, ConfigError>
40    where
41        R: TryInto<TablePath>,
42        <R as TryInto<TablePath>>::Error: Debug,
43        ConfigError: From<<R as TryInto<TablePath>>::Error>,
44    {
45        let path: TablePath = path.try_into()?;
46        Ok(Self {
47            path,
48            fields: Default::default(),
49        })
50    }
51
52    pub fn add_column(mut self, field: ColumnConfig) -> Result<Self, ConfigError> {
53        self.fields.try_insert(field)?;
54        Ok(self)
55    }
56
57    pub fn get_column(
58        &self,
59        name: impl Into<String>,
60    ) -> Result<Option<&ColumnConfig>, ConfigError> {
61        let name: String = name.into();
62        Ok(self.fields.get(&name))
63    }
64
65    pub fn has_column(&self, name: impl Into<String>) -> Result<bool, ConfigError> {
66        let name: String = name.into();
67        Ok(self.fields.has_entry(&name))
68    }
69
70    /// Sorts all indexes by type for each field. Indexes are sorted in place.
71    pub fn sort_indexes_by_type(&mut self) {
72        self.fields
73            .iter_mut()
74            .for_each(ColumnConfig::sort_indexes_by_type);
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use std::error::Error;
82
83    #[test]
84    fn add_and_get_column() -> Result<(), Box<dyn Error>> {
85        let config = TableConfig::new("users")?.add_column(ColumnConfig::build("name"))?;
86
87        assert!(matches!(
88            config.get_column("name")?,
89            Some(ColumnConfig { name, .. }) if name == "name"
90        ));
91
92        Ok(())
93    }
94
95    #[test]
96    fn add_dupe() -> Result<(), Box<dyn Error>> {
97        let config = TableConfig::new("users")?.add_column(ColumnConfig::build("name"))?;
98
99        assert!(config.add_column(ColumnConfig::build("name")).is_err());
100
101        Ok(())
102    }
103}