authly_common/
service.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Authly service utilities and helpers

use std::collections::{hash_map, HashMap};

use fnv::FnvHashSet;

use crate::id::AttrId;

/// A namespaced property mapping maps human-readable property and attribute labels to [AttrId]s.
#[derive(Clone, Default)]
pub struct NamespacePropertyMapping {
    namespaces: HashMap<String, PropertyMappings>,
}

/// A property mapping maps human-readable property and attribute labels to [AttrId]s.
#[derive(Clone, Default)]
pub struct PropertyMappings {
    properties: HashMap<String, AttributeMappings>,
}

/// Attribute mappings for a property.
#[derive(Clone, Default)]
pub struct AttributeMappings {
    attributes: HashMap<String, AttrId>,
}

impl NamespacePropertyMapping {
    /// Get a mutable reference to the namespace
    pub fn namespace_mut(&mut self, namespace_label: String) -> &mut PropertyMappings {
        self.namespaces.entry(namespace_label).or_default()
    }

    /// Get the object ID of a single property/attribute label pair, if found.
    pub fn attribute_object_id(
        &self,
        namespace_label: &str,
        property_label: &str,
        attribute_label: &str,
    ) -> Option<AttrId> {
        self.namespaces
            .get(namespace_label)?
            .properties
            .get(property_label)?
            .attributes
            .get(attribute_label)
            .cloned()
    }

    /// Translate the given namespace/property/attribute labels to underlying [AttrId]s.
    pub fn translate<'a>(
        &self,
        attributes: impl IntoIterator<Item = (&'a str, &'a str, &'a str)>,
    ) -> FnvHashSet<AttrId> {
        let mut output = FnvHashSet::default();
        for (namespace, prop, attr) in attributes {
            let Some(prop_mappings) = self.namespaces.get(namespace) else {
                continue;
            };
            let Some(attr_mappings) = prop_mappings.properties.get(prop) else {
                continue;
            };
            let Some(attr_id) = attr_mappings.attributes.get(attr) else {
                continue;
            };

            output.insert(*attr_id);
        }

        output
    }
}

impl PropertyMappings {
    /// Get a mutable reference to the attribute mappings of a property.
    pub fn property_mut(&mut self, property_label: String) -> &mut AttributeMappings {
        self.properties.entry(property_label).or_default()
    }
}

impl AttributeMappings {
    /// Put a new attribute id under the attribute label.
    pub fn put(&mut self, attribute_label: String, attribute_id: AttrId) {
        self.attributes
            .entry(attribute_label)
            .insert_entry(attribute_id);
    }
}

impl IntoIterator for NamespacePropertyMapping {
    type IntoIter = hash_map::IntoIter<String, PropertyMappings>;
    type Item = (String, PropertyMappings);

    fn into_iter(self) -> Self::IntoIter {
        self.namespaces.into_iter()
    }
}

impl<'a> IntoIterator for &'a NamespacePropertyMapping {
    type IntoIter = hash_map::Iter<'a, String, PropertyMappings>;
    type Item = (&'a String, &'a PropertyMappings);

    fn into_iter(self) -> Self::IntoIter {
        self.namespaces.iter()
    }
}

impl IntoIterator for PropertyMappings {
    type IntoIter = hash_map::IntoIter<String, AttributeMappings>;
    type Item = (String, AttributeMappings);

    fn into_iter(self) -> Self::IntoIter {
        self.properties.into_iter()
    }
}

impl<'a> IntoIterator for &'a PropertyMappings {
    type IntoIter = hash_map::Iter<'a, String, AttributeMappings>;
    type Item = (&'a String, &'a AttributeMappings);

    fn into_iter(self) -> Self::IntoIter {
        self.properties.iter()
    }
}

impl IntoIterator for AttributeMappings {
    type IntoIter = hash_map::IntoIter<String, AttrId>;
    type Item = (String, AttrId);

    fn into_iter(self) -> Self::IntoIter {
        self.attributes.into_iter()
    }
}

impl<'a> IntoIterator for &'a AttributeMappings {
    type IntoIter = hash_map::Iter<'a, String, AttrId>;
    type Item = (&'a String, &'a AttrId);

    fn into_iter(self) -> Self::IntoIter {
        self.attributes.iter()
    }
}