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 smol_str::SmolStr;
58    use std::collections::{BTreeMap, HashMap, HashSet};
59    use std::sync::Arc;
60
61    #[test]
62    fn entities_roundtrip() {
63        // Empty Test
64        let entities1 = entities::Entities::new();
65        assert_eq!(
66            entities1,
67            entities::Entities::from(&models::Entities::from(&entities1))
68        );
69
70        // Single Element Test
71        let attrs = (1..=7)
72            .map(|id| (format!("{id}").into(), ast::RestrictedExpr::val(true)))
73            .collect::<HashMap<SmolStr, _>>();
74        let entity = Arc::new(
75            ast::Entity::new(
76                r#"Foo::"bar""#.parse().unwrap(),
77                attrs.clone(),
78                HashSet::new(),
79                HashSet::new(),
80                BTreeMap::new(),
81                extensions::Extensions::none(),
82            )
83            .unwrap(),
84        );
85        let mut entities2 = entities::Entities::new();
86        entities2 = entities2
87            .add_entities(
88                [entity.clone()],
89                None::<&entities::NoEntitiesSchema>,
90                entities::TCComputation::AssumeAlreadyComputed,
91                extensions::Extensions::none(),
92            )
93            .unwrap();
94        assert_eq!(
95            entities2,
96            entities::Entities::from(&models::Entities::from(&entities2))
97        );
98
99        // Two Element Test
100        let entity2 = Arc::new(
101            ast::Entity::new(
102                r#"Bar::"foo""#.parse().unwrap(),
103                attrs,
104                HashSet::new(),
105                HashSet::new(),
106                BTreeMap::new(),
107                extensions::Extensions::none(),
108            )
109            .unwrap(),
110        );
111        let mut entities3 = entities::Entities::new();
112        entities3 = entities3
113            .add_entities(
114                [entity, entity2],
115                None::<&entities::NoEntitiesSchema>,
116                entities::TCComputation::AssumeAlreadyComputed,
117                extensions::Extensions::none(),
118            )
119            .unwrap();
120        assert_eq!(
121            entities3,
122            entities::Entities::from(&models::Entities::from(&entities3))
123        );
124    }
125}