cipherstash_dynamodb/encrypted_table/
attribute_name.rs

1/// Represents the name of an attribute for storage in the database.
2/// For the most part, this is just a `String`, but it ensures that special columns
3/// like `pk` and `sk` are stored in the database as `__pk` and `__sk` respectively.
4#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub struct AttributeName(String);
6
7impl AttributeName {
8    pub fn new(name: impl Into<String>) -> Self {
9        // Always store pk and sk as __pk and __sk
10        Self(to_inner_pksk(name.into()))
11    }
12
13    /// Returns the name of the attribute as it should be stored in the database.
14    /// For example, `pk` will be stored as `__pk`.
15    pub fn as_stored_name(&self) -> &str {
16        to_inner_pksk_ref(&self.0)
17    }
18
19    /// Returns the name of the attribute as it should be stored in the database.
20    /// For example, `pk` will be stored as `__pk`.
21    pub fn into_stored_name(self) -> String {
22        to_inner_pksk(self.0)
23    }
24
25    /// Returns the name of the attribute as it should be displayed externally.
26    /// For example, `__pk` will be displayed as `pk`.
27    pub fn as_external_name(&self) -> &str {
28        from_inner_pksk_ref(&self.0)
29    }
30}
31
32impl From<String> for AttributeName {
33    fn from(name: String) -> Self {
34        Self::new(name)
35    }
36}
37
38impl From<&str> for AttributeName {
39    fn from(name: &str) -> Self {
40        Self::new(name)
41    }
42}
43
44#[inline]
45fn to_inner_pksk(key: String) -> String {
46    match key.as_str() {
47        "pk" => "__pk".into(),
48        "sk" => "__sk".into(),
49        _ => key,
50    }
51}
52
53#[inline]
54fn to_inner_pksk_ref(key: &str) -> &str {
55    match key {
56        "pk" => "__pk",
57        "sk" => "__sk",
58        _ => key,
59    }
60}
61
62#[inline]
63fn from_inner_pksk_ref(key: &str) -> &str {
64    match key {
65        "__pk" => "pk",
66        "__sk" => "sk",
67        _ => key,
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_attribute_name() {
77        let name = AttributeName::new("pk");
78        assert_eq!(name.as_stored_name(), "__pk");
79        assert_eq!(name.as_external_name(), "pk");
80
81        let name = AttributeName::new("sk");
82        assert_eq!(name.as_stored_name(), "__sk");
83        assert_eq!(name.as_external_name(), "sk");
84
85        let name = AttributeName::new("name");
86        assert_eq!(name.as_stored_name(), "name");
87        assert_eq!(name.as_external_name(), "name");
88    }
89}