scuffle_cedar_policy/
entity.rs1use std::collections::BTreeMap;
2
3use crate::{CedarChild, CedarEntity, CedarId, EntityTypeName, EntityUid};
4
5#[derive(serde_derive::Serialize)]
6struct StaticEntityUid {
7 #[serde(rename = "type")]
8 ty: EntityTypeName,
9 id: smol_str::SmolStr,
10}
11
12#[derive(serde_derive::Serialize, bon::Builder)]
14#[builder(start_fn(
15 name = builder_internal,
16 vis = "",
17))]
18pub struct Entity<E>
19where
20 E: CedarEntity,
21{
22 #[builder(start_fn)]
23 uid: StaticEntityUid,
24
25 #[builder(start_fn)]
26 attrs: E::Attrs,
27
28 #[builder(field)]
29 parents: Vec<StaticEntityUid>,
30 #[builder(field)]
31 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
32 tags: BTreeMap<smol_str::SmolStr, E::TagType>,
33}
34
35impl<E: CedarEntity, S: entity_builder::IsComplete> From<EntityBuilder<E, S>> for Entity<E> {
36 fn from(value: EntityBuilder<E, S>) -> Self {
37 value.build()
38 }
39}
40
41impl<E: CedarEntity> Entity<E> {
42 pub fn builder(id: E::Id, attrs: E::Attrs) -> EntityBuilder<E> {
44 Self::builder_internal(
45 StaticEntityUid {
46 ty: E::TYPE_NAME,
47 id: id.into_smol_string(),
48 },
49 attrs,
50 )
51 }
52}
53
54impl<E: CedarEntity, S: entity_builder::State> EntityBuilder<E, S> {
55 pub fn parent<P>(mut self, id: impl Into<P::Id>) -> Self
57 where
58 E: CedarChild<P>,
59 P: CedarEntity,
60 {
61 self.parents.push(StaticEntityUid {
62 ty: P::TYPE_NAME,
63 id: id.into().into_smol_string(),
64 });
65 self
66 }
67
68 pub fn tag(mut self, key: impl Into<smol_str::SmolStr>, value: impl Into<E::TagType>) -> Self {
70 self.tags.insert(key.into(), value.into());
71 self
72 }
73}
74
75impl<E: CedarEntity> Entity<E> {
76 pub fn entity_uid(&self) -> EntityUid<E> {
78 EntityUid::new_from_str(self.uid.id.clone())
79 }
80}