cedar_policy/proto/
entities.rs

1/*
2 * Copyright Cedar Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#![allow(clippy::use_self)]
18
19use super::models;
20use cedar_policy_core::{ast, entities, extensions};
21
22impl From<&models::Entities> for entities::Entities {
23    // PANIC SAFETY: experimental feature
24    #[allow(clippy::expect_used)]
25    fn from(v: &models::Entities) -> Self {
26        let entities: Vec<ast::Entity> = v.entities.iter().map(ast::Entity::from).collect();
27
28        // REVIEW (before stabilization): does `AssumeAlreadyComputed` make
29        // sense here? It will be the case for protobufs produced from our
30        // own serialization code, but others could produce protobufs in other
31        // ways that may not be TC
32        entities::Entities::from_entities(
33            entities,
34            None::<&entities::NoEntitiesSchema>,
35            entities::TCComputation::AssumeAlreadyComputed,
36            extensions::Extensions::all_available(),
37        )
38        .expect("protobuf entities should be valid")
39    }
40}
41
42impl From<&entities::Entities> for models::Entities {
43    fn from(v: &entities::Entities) -> Self {
44        assert!(
45            !v.is_partial(),
46            "protobuf does not support encoding partial Entities"
47        );
48        Self {
49            entities: v.iter().map(models::Entity::from).collect(),
50        }
51    }
52}
53
54#[cfg(test)]
55mod test {
56    use super::*;
57    use cedar_policy_core::assert_deep_eq;
58    use smol_str::SmolStr;
59    use std::collections::{BTreeMap, HashMap, HashSet};
60    use std::sync::Arc;
61
62    #[test]
63    fn entities_roundtrip() {
64        // Empty Test
65        let entities1 = entities::Entities::new();
66        assert_deep_eq!(
67            entities1,
68            entities::Entities::from(&models::Entities::from(&entities1))
69        );
70
71        // Single Element Test
72        let attrs = (1..=7)
73            .map(|id| (format!("{id}").into(), ast::RestrictedExpr::val(true)))
74            .collect::<HashMap<SmolStr, _>>();
75        let entity = Arc::new(
76            ast::Entity::new(
77                r#"Foo::"bar""#.parse().unwrap(),
78                attrs.clone(),
79                HashSet::new(),
80                HashSet::new(),
81                BTreeMap::new(),
82                extensions::Extensions::none(),
83            )
84            .unwrap(),
85        );
86        let mut entities2 = entities::Entities::new();
87        entities2 = entities2
88            .add_entities(
89                [entity.clone()],
90                None::<&entities::NoEntitiesSchema>,
91                entities::TCComputation::AssumeAlreadyComputed,
92                extensions::Extensions::none(),
93            )
94            .unwrap();
95        assert_deep_eq!(
96            entities2,
97            entities::Entities::from(&models::Entities::from(&entities2))
98        );
99
100        // Two Element Test
101        let entity2 = Arc::new(
102            ast::Entity::new(
103                r#"Bar::"foo""#.parse().unwrap(),
104                attrs,
105                HashSet::new(),
106                HashSet::new(),
107                BTreeMap::new(),
108                extensions::Extensions::none(),
109            )
110            .unwrap(),
111        );
112        let mut entities3 = entities::Entities::new();
113        entities3 = entities3
114            .add_entities(
115                [entity, entity2],
116                None::<&entities::NoEntitiesSchema>,
117                entities::TCComputation::AssumeAlreadyComputed,
118                extensions::Extensions::none(),
119            )
120            .unwrap();
121        assert_deep_eq!(
122            entities3,
123            entities::Entities::from(&models::Entities::from(&entities3))
124        );
125    }
126}