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};
21use std::sync::Arc;
22
23impl From<&models::Entities> for entities::Entities {
24    // PANIC SAFETY: experimental feature
25    #[allow(clippy::expect_used)]
26    fn from(v: &models::Entities) -> Self {
27        let entities: Vec<Arc<ast::Entity>> = v
28            .entities
29            .iter()
30            .map(|e| Arc::new(ast::Entity::from(e)))
31            .collect();
32
33        #[cfg(not(feature = "partial-eval"))]
34        let result = entities::Entities::new();
35
36        #[cfg(feature = "partial-eval")]
37        let mut result = entities::Entities::new();
38        #[cfg(feature = "partial-eval")]
39        if v.mode == models::Mode::Partial as i32 {
40            result = result.partial();
41        }
42
43        result
44            .add_entities(
45                entities,
46                None::<&entities::NoEntitiesSchema>,
47                entities::TCComputation::AssumeAlreadyComputed,
48                extensions::Extensions::none(),
49            )
50            .expect("Should be able to add entities")
51    }
52}
53
54impl From<&entities::Entities> for models::Entities {
55    fn from(v: &entities::Entities) -> Self {
56        let entities: Vec<models::Entity> = v.iter().map(models::Entity::from).collect();
57
58        if cfg!(feature = "partial-eval") && v.is_partial() {
59            Self {
60                entities,
61                mode: models::Mode::Partial.into(),
62            }
63        } else {
64            Self {
65                entities,
66                mode: models::Mode::Concrete.into(),
67            }
68        }
69    }
70}
71
72#[cfg(test)]
73mod test {
74    use super::*;
75    use smol_str::SmolStr;
76    use std::collections::{BTreeMap, HashMap, HashSet};
77
78    #[test]
79    fn entities_roundtrip() {
80        // Empty Test
81        let entities1 = entities::Entities::new();
82        assert_eq!(
83            entities1,
84            entities::Entities::from(&models::Entities::from(&entities1))
85        );
86
87        // Single Element Test
88        let attrs = (1..=7)
89            .map(|id| (format!("{id}").into(), ast::RestrictedExpr::val(true)))
90            .collect::<HashMap<SmolStr, _>>();
91        let entity = Arc::new(
92            ast::Entity::new(
93                r#"Foo::"bar""#.parse().unwrap(),
94                attrs.clone(),
95                HashSet::new(),
96                BTreeMap::new(),
97                extensions::Extensions::none(),
98            )
99            .unwrap(),
100        );
101        let mut entities2 = entities::Entities::new();
102        entities2 = entities2
103            .add_entities(
104                std::iter::once(entity.clone()),
105                None::<&entities::NoEntitiesSchema>,
106                entities::TCComputation::AssumeAlreadyComputed,
107                extensions::Extensions::none(),
108            )
109            .unwrap();
110        assert_eq!(
111            entities2,
112            entities::Entities::from(&models::Entities::from(&entities2))
113        );
114
115        // Two Element Test
116        let entity2 = Arc::new(
117            ast::Entity::new(
118                r#"Bar::"foo""#.parse().unwrap(),
119                attrs,
120                HashSet::new(),
121                BTreeMap::new(),
122                extensions::Extensions::none(),
123            )
124            .unwrap(),
125        );
126        let mut entities3 = entities::Entities::new();
127        entities3 = entities3
128            .add_entities(
129                [entity, entity2],
130                None::<&entities::NoEntitiesSchema>,
131                entities::TCComputation::AssumeAlreadyComputed,
132                extensions::Extensions::none(),
133            )
134            .unwrap();
135        assert_eq!(
136            entities3,
137            entities::Entities::from(&models::Entities::from(&entities3))
138        );
139    }
140}