Skip to main content

cedrus_cedar/
lib.rs

1#![doc = include_str!("../README.md")]
2#![allow(clippy::result_large_err)]
3
4pub mod proto {
5    include!(concat!(env!("OUT_DIR"), "/cedar.rs"));
6}
7
8use std::{
9    borrow::Borrow,
10    collections::{HashMap, HashSet},
11    hash::Hash,
12    str::{self, FromStr},
13};
14
15use serde::{Deserialize, Serialize};
16use utoipa::ToSchema;
17
18#[derive(
19    Debug, Default, Clone, Eq, PartialOrd, Ord, Hash, PartialEq, Serialize, Deserialize, ToSchema,
20)]
21pub struct EntityUid {
22    #[serde(rename = "type")]
23    r#type: String,
24    id: String,
25}
26
27impl EntityUid {
28    pub fn new(r#type: String, id: String) -> Self {
29        Self { r#type, id }
30    }
31
32    pub fn type_name(&self) -> &str {
33        &self.r#type
34    }
35
36    pub fn id(&self) -> &str {
37        &self.id
38    }
39}
40
41impl From<String> for EntityUid {
42    fn from(value: String) -> Self {
43        let mut parts = value.split("::");
44        let list: Vec<&str> = parts.by_ref().collect();
45        let (last, elements) = list.split_last().unwrap();
46        let r#type = elements.join("::");
47        let id = last.to_string();
48        Self { r#type, id }
49    }
50}
51
52impl From<&str> for EntityUid {
53    fn from(value: &str) -> Self {
54        let mut parts = value.split("::");
55        let list: Vec<&str> = parts.by_ref().collect();
56        let (last, elements) = list.split_last().unwrap();
57        let r#type = elements.join("::");
58        let id = last.to_string();
59        Self { r#type, id }
60    }
61}
62
63impl From<cedar_policy::EntityUid> for EntityUid {
64    fn from(value: cedar_policy::EntityUid) -> Self {
65        Self {
66            r#type: value.type_name().to_string(),
67            id: value.id().unescaped().to_string(),
68        }
69    }
70}
71
72impl From<EntityUid> for cedar_policy::EntityUid {
73    fn from(val: EntityUid) -> Self {
74        cedar_policy::EntityUid::from_type_name_and_id(
75            cedar_policy::EntityTypeName::from_str(&val.r#type).unwrap(),
76            cedar_policy::EntityId::from_str(&val.id).unwrap(),
77        )
78    }
79}
80
81impl From<proto::EntityUid> for EntityUid {
82    fn from(value: proto::EntityUid) -> Self {
83        Self {
84            r#type: value.r#type,
85            id: value.name,
86        }
87    }
88}
89
90impl From<EntityUid> for proto::EntityUid {
91    fn from(val: EntityUid) -> Self {
92        proto::EntityUid {
93            r#type: val.r#type,
94            name: val.id,
95        }
96    }
97}
98
99impl std::fmt::Display for EntityUid {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        write!(f, "{}::{}", self.r#type, self.id)
102    }
103}
104
105#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
106pub struct ExtensionFn {
107    #[serde(rename = "fn")]
108    r#fn: String,
109    arg: String,
110}
111
112impl From<proto::ExtensionFn> for ExtensionFn {
113    fn from(value: proto::ExtensionFn) -> Self {
114        Self {
115            r#fn: value.r#fn,
116            arg: value.arg,
117        }
118    }
119}
120
121impl From<ExtensionFn> for proto::ExtensionFn {
122    fn from(val: ExtensionFn) -> Self {
123        proto::ExtensionFn {
124            r#fn: val.r#fn,
125            arg: val.arg,
126        }
127    }
128}
129
130#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
131pub struct EntityUidEscape {
132    #[serde(rename = "__entity")]
133    entity: EntityUid,
134}
135
136impl From<cedar_policy::EntityUid> for EntityUidEscape {
137    fn from(value: cedar_policy::EntityUid) -> Self {
138        let entity = EntityUid {
139            r#type: value.type_name().to_string(),
140            id: value.id().unescaped().to_string(),
141        };
142        Self { entity }
143    }
144}
145
146impl From<EntityUidEscape> for cedar_policy::EntityUid {
147    fn from(val: EntityUidEscape) -> Self {
148        cedar_policy::EntityUid::from_type_name_and_id(
149            cedar_policy::EntityTypeName::from_str(&val.entity.r#type).unwrap(),
150            cedar_policy::EntityId::from_str(&val.entity.id).unwrap(),
151        )
152    }
153}
154
155impl From<proto::EntityUidEscape> for EntityUidEscape {
156    fn from(value: proto::EntityUidEscape) -> Self {
157        let entity = EntityUid {
158            r#type: value.r#type,
159            id: value.name,
160        };
161        Self { entity }
162    }
163}
164
165impl From<EntityUidEscape> for proto::EntityUidEscape {
166    fn from(val: EntityUidEscape) -> Self {
167        proto::EntityUidEscape {
168            r#type: val.entity.r#type,
169            name: val.entity.id,
170        }
171    }
172}
173
174impl From<EntityUid> for EntityUidEscape {
175    fn from(value: EntityUid) -> Self {
176        Self { entity: value }
177    }
178}
179
180impl From<EntityUidEscape> for EntityUid {
181    fn from(val: EntityUidEscape) -> Self {
182        EntityUid {
183            r#type: val.entity.r#type,
184            id: val.entity.id,
185        }
186    }
187}
188
189impl std::fmt::Display for EntityUidEscape {
190    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191        write!(f, "{}::{}", self.entity.r#type, self.entity.id)
192    }
193}
194
195#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
196pub struct ExtensionFnEscape {
197    #[serde(rename = "__extn")]
198    extn: ExtensionFn,
199}
200
201impl From<ExtensionFn> for ExtensionFnEscape {
202    fn from(value: ExtensionFn) -> Self {
203        Self { extn: value }
204    }
205}
206
207impl From<ExtensionFnEscape> for ExtensionFn {
208    fn from(val: ExtensionFnEscape) -> Self {
209        ExtensionFn {
210            r#fn: val.extn.r#fn,
211            arg: val.extn.arg,
212        }
213    }
214}
215
216impl From<proto::ExtensionFnEscape> for ExtensionFnEscape {
217    fn from(value: proto::ExtensionFnEscape) -> Self {
218        let extn = ExtensionFn {
219            r#fn: value.r#fn,
220            arg: value.arg,
221        };
222        Self { extn }
223    }
224}
225
226impl From<ExtensionFnEscape> for proto::ExtensionFnEscape {
227    fn from(val: ExtensionFnEscape) -> Self {
228        proto::ExtensionFnEscape {
229            r#fn: val.extn.r#fn,
230            arg: val.extn.arg,
231        }
232    }
233}
234
235pub mod entity {
236    use super::*;
237
238    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
239    #[serde(untagged)]
240    pub enum EntityAttr {
241        String(String),
242        Number(i64),
243        Boolean(bool),
244        #[schema(no_recursion)]
245        Set(Vec<EntityAttr>),
246        #[schema(no_recursion)]
247        Record(HashMap<String, EntityAttr>),
248        EntityUid(EntityUid),
249        Function(ExtensionFn),
250        EntityUidEscape(EntityUidEscape),
251        FunctionEscape(ExtensionFnEscape),
252    }
253
254    impl Default for EntityAttr {
255        fn default() -> Self {
256            EntityAttr::String(String::default())
257        }
258    }
259
260    impl From<proto::entity::EntityAttr> for EntityAttr {
261        fn from(value: proto::entity::EntityAttr) -> Self {
262            match value.value.unwrap() {
263                proto::entity::entity_attr::Value::S(s) => Self::String(s),
264                proto::entity::entity_attr::Value::I(n) => Self::Number(n),
265                proto::entity::entity_attr::Value::B(b) => Self::Boolean(b),
266                proto::entity::entity_attr::Value::Euid(e) => Self::EntityUid(e.into()),
267                proto::entity::entity_attr::Value::Efn(f) => Self::Function(f.into()),
268                proto::entity::entity_attr::Value::Euide(e) => Self::EntityUidEscape(e.into()),
269                proto::entity::entity_attr::Value::Efne(f) => Self::FunctionEscape(f.into()),
270                proto::entity::entity_attr::Value::Set(set) => {
271                    let attrs = set
272                        .elements
273                        .into_iter()
274                        .map(|a| a.into())
275                        .collect::<Vec<EntityAttr>>();
276                    Self::Set(attrs)
277                }
278                proto::entity::entity_attr::Value::Record(record) => {
279                    let attrs = record
280                        .items
281                        .into_iter()
282                        .map(|(k, v)| (k, v.into()))
283                        .collect::<HashMap<String, EntityAttr>>();
284                    Self::Record(attrs)
285                }
286            }
287        }
288    }
289
290    impl From<EntityAttr> for proto::entity::EntityAttr {
291        fn from(val: EntityAttr) -> Self {
292            let value = match val {
293                EntityAttr::String(s) => proto::entity::entity_attr::Value::S(s),
294                EntityAttr::Number(n) => proto::entity::entity_attr::Value::I(n),
295                EntityAttr::Boolean(b) => proto::entity::entity_attr::Value::B(b),
296                EntityAttr::EntityUid(e) => proto::entity::entity_attr::Value::Euid(e.into()),
297                EntityAttr::Function(f) => proto::entity::entity_attr::Value::Efn(f.into()),
298                EntityAttr::EntityUidEscape(e) => {
299                    proto::entity::entity_attr::Value::Euide(e.into())
300                }
301                EntityAttr::FunctionEscape(f) => proto::entity::entity_attr::Value::Efne(f.into()),
302                EntityAttr::Set(set) => {
303                    let elements = set
304                        .into_iter()
305                        .map(|a| a.into())
306                        .collect::<Vec<proto::entity::EntityAttr>>();
307                    proto::entity::entity_attr::Value::Set(proto::entity::Set { elements })
308                }
309                EntityAttr::Record(record) => {
310                    let items = record
311                        .into_iter()
312                        .map(|(k, v)| (k, v.into()))
313                        .collect::<HashMap<String, proto::entity::EntityAttr>>();
314                    proto::entity::entity_attr::Value::Record(proto::entity::Record { items })
315                }
316            };
317
318            proto::entity::EntityAttr { value: Some(value) }
319        }
320    }
321}
322
323#[derive(Debug, Default, Clone, Serialize, Deserialize, ToSchema)]
324#[serde(default)]
325pub struct Entity {
326    uid: EntityUid,
327    attrs: HashMap<String, entity::EntityAttr>,
328    parents: HashSet<EntityUid>,
329    tags: HashMap<String, entity::EntityAttr>,
330}
331
332impl Entity {
333    pub fn new(
334        uid: EntityUid,
335        attrs: HashMap<String, entity::EntityAttr>,
336        parents: HashSet<EntityUid>,
337    ) -> Self {
338        Self {
339            uid,
340            attrs,
341            parents,
342            tags: HashMap::new(),
343        }
344    }
345
346    pub fn new_no_attrs(uid: EntityUid, parents: HashSet<EntityUid>) -> Self {
347        Self {
348            uid,
349            attrs: HashMap::new(),
350            parents,
351            tags: HashMap::new(),
352        }
353    }
354
355    pub fn new_with_tags(
356        uid: EntityUid,
357        attrs: HashMap<String, entity::EntityAttr>,
358        parents: HashSet<EntityUid>,
359        tags: HashMap<String, entity::EntityAttr>,
360    ) -> Self {
361        Self {
362            uid,
363            attrs,
364            parents,
365            tags,
366        }
367    }
368
369    pub fn uid(&self) -> &EntityUid {
370        &self.uid
371    }
372
373    pub fn parents(&self) -> &HashSet<EntityUid> {
374        &self.parents
375    }
376
377    pub fn attrs(&self) -> &HashMap<String, entity::EntityAttr> {
378        &self.attrs
379    }
380
381    pub fn tags(&self) -> &HashMap<String, entity::EntityAttr> {
382        &self.tags
383    }
384
385    pub fn to_cedar_entity(
386        &self,
387        cedar_schema: Option<&cedar_policy::Schema>,
388    ) -> Result<cedar_policy::Entity, cedar_policy::entities_errors::EntitiesError> {
389        let json = serde_json::to_value(self).unwrap();
390        cedar_policy::Entity::from_json_value(json, cedar_schema)
391    }
392}
393
394impl PartialEq for Entity {
395    fn eq(&self, other: &Self) -> bool {
396        self.uid == other.uid
397    }
398}
399
400impl Eq for Entity {}
401
402impl Hash for Entity {
403    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
404        self.uid.hash(state);
405    }
406}
407
408impl TryFrom<cedar_policy::Entity> for Entity {
409    type Error = cedar_policy::entities_errors::EntitiesError;
410
411    fn try_from(value: cedar_policy::Entity) -> Result<Self, Self::Error> {
412        match value.to_json_value() {
413            Ok(json) => Ok(serde_json::from_value(json).unwrap()),
414            Err(e) => Err(e),
415        }
416    }
417}
418
419impl TryInto<cedar_policy::Entity> for Entity {
420    type Error = cedar_policy::entities_errors::EntitiesError;
421
422    fn try_into(self) -> Result<cedar_policy::Entity, Self::Error> {
423        cedar_policy::Entity::from_json_value(serde_json::to_value(self).unwrap(), None)
424    }
425}
426
427impl From<proto::Entity> for Entity {
428    fn from(value: proto::Entity) -> Self {
429        let uid = value.uid.unwrap().into();
430        let attrs = value
431            .attrs
432            .into_iter()
433            .map(|(k, v)| (k, v.into()))
434            .collect::<HashMap<String, entity::EntityAttr>>();
435        let parents = value
436            .parents
437            .into_iter()
438            .map(|p| p.into())
439            .collect::<HashSet<EntityUid>>();
440        let tags = value
441            .tags
442            .into_iter()
443            .map(|(k, v)| (k, v.into()))
444            .collect::<HashMap<String, entity::EntityAttr>>();
445
446        Self {
447            uid,
448            attrs,
449            parents,
450            tags,
451        }
452    }
453}
454
455impl From<Entity> for proto::Entity {
456    fn from(val: Entity) -> Self {
457        let uid = Some(val.uid.into());
458        let attrs = val
459            .attrs
460            .into_iter()
461            .map(|(k, v)| (k, v.into()))
462            .collect::<HashMap<String, proto::entity::EntityAttr>>();
463        let parents = val
464            .parents
465            .into_iter()
466            .map(|p| p.into())
467            .collect::<Vec<proto::EntityUid>>();
468        let tags = val
469            .tags
470            .into_iter()
471            .map(|(k, v)| (k, v.into()))
472            .collect::<HashMap<String, proto::entity::EntityAttr>>();
473
474        proto::Entity {
475            uid,
476            attrs,
477            parents,
478            tags,
479        }
480    }
481}
482
483pub mod schema {
484    use super::*;
485
486    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
487    #[schema(as = schema::TypeJson)]
488    #[serde(tag = "type")]
489    pub enum TypeJson {
490        Long {
491            #[serde(skip_serializing_if = "Option::is_none")]
492            required: Option<bool>,
493        },
494        String {
495            #[serde(skip_serializing_if = "Option::is_none")]
496            required: Option<bool>,
497        },
498        Boolean {
499            #[serde(skip_serializing_if = "Option::is_none")]
500            required: Option<bool>,
501        },
502        Set {
503            #[schema(no_recursion)]
504            element: Box<TypeJson>,
505            #[serde(skip_serializing_if = "Option::is_none")]
506            required: Option<bool>,
507        },
508        Entity {
509            name: String,
510            #[serde(skip_serializing_if = "Option::is_none")]
511            required: Option<bool>,
512        },
513        Record {
514            #[schema(no_recursion)]
515            attributes: HashMap<String, TypeJson>,
516            #[serde(skip_serializing_if = "Option::is_none")]
517            required: Option<bool>,
518        },
519        Extension {
520            name: String,
521            #[serde(skip_serializing_if = "Option::is_none")]
522            required: Option<bool>,
523        },
524        EntityOrCommon {
525            name: String,
526            #[serde(skip_serializing_if = "Option::is_none")]
527            required: Option<bool>,
528        },
529    }
530
531    impl Default for TypeJson {
532        fn default() -> Self {
533            Self::String { required: None }
534        }
535    }
536
537    impl From<proto::schema::TypeJson> for TypeJson {
538        fn from(value: proto::schema::TypeJson) -> Self {
539            match value.value.unwrap() {
540                proto::schema::type_json::Value::L(long) => Self::Long {
541                    required: match long.required {
542                        true => None,
543                        false => Some(false),
544                    },
545                },
546                proto::schema::type_json::Value::S(string) => Self::String {
547                    required: match string.required {
548                        true => None,
549                        false => Some(false),
550                    },
551                },
552                proto::schema::type_json::Value::B(boolean) => Self::Boolean {
553                    required: match boolean.required {
554                        true => None,
555                        false => Some(false),
556                    },
557                },
558                proto::schema::type_json::Value::Set(set) => Self::Set {
559                    element: Box::new(TypeJson::from(*set.element.unwrap())),
560                    required: match set.required {
561                        true => None,
562                        false => Some(false),
563                    },
564                },
565                proto::schema::type_json::Value::Entity(entity) => Self::Entity {
566                    name: entity.name,
567                    required: match entity.required {
568                        true => None,
569                        false => Some(false),
570                    },
571                },
572                proto::schema::type_json::Value::Record(record) => Self::Record {
573                    attributes: record
574                        .attributes
575                        .into_iter()
576                        .map(|(k, v)| (k, TypeJson::from(v)))
577                        .collect(),
578                    required: match record.required {
579                        true => None,
580                        false => Some(false),
581                    },
582                },
583                proto::schema::type_json::Value::Ext(extension) => Self::Extension {
584                    name: extension.name,
585                    required: match extension.required {
586                        true => None,
587                        false => Some(false),
588                    },
589                },
590                proto::schema::type_json::Value::Eorc(entity_or_common) => Self::EntityOrCommon {
591                    name: entity_or_common.name,
592                    required: match entity_or_common.required {
593                        true => None,
594                        false => Some(false),
595                    },
596                },
597            }
598        }
599    }
600
601    impl From<TypeJson> for proto::schema::TypeJson {
602        fn from(val: TypeJson) -> Self {
603            let value = match val {
604                TypeJson::Long { required } => {
605                    proto::schema::type_json::Value::L(proto::schema::Long {
606                        required: required.unwrap_or(true),
607                    })
608                }
609                TypeJson::String { required } => {
610                    proto::schema::type_json::Value::S(proto::schema::String {
611                        required: required.unwrap_or(true),
612                    })
613                }
614                TypeJson::Boolean { required } => {
615                    proto::schema::type_json::Value::B(proto::schema::Boolean {
616                        required: required.unwrap_or(true),
617                    })
618                }
619                TypeJson::Set { element, required } => proto::schema::type_json::Value::Set(
620                    ::prost::alloc::boxed::Box::new(proto::schema::Set {
621                        element: Some(::prost::alloc::boxed::Box::new((*element).into())),
622                        required: required.unwrap_or(true),
623                    }),
624                ),
625                TypeJson::Entity { name, required } => {
626                    proto::schema::type_json::Value::Entity(proto::schema::Entity {
627                        name,
628                        required: required.unwrap_or(true),
629                    })
630                }
631                TypeJson::Record {
632                    attributes,
633                    required,
634                } => proto::schema::type_json::Value::Record(proto::schema::Record {
635                    attributes: attributes.into_iter().map(|(k, v)| (k, v.into())).collect(),
636                    required: required.unwrap_or(true),
637                }),
638                TypeJson::Extension { name, required } => {
639                    proto::schema::type_json::Value::Ext(proto::schema::Extension {
640                        name,
641                        required: required.unwrap_or(true),
642                    })
643                }
644                TypeJson::EntityOrCommon { name, required } => {
645                    proto::schema::type_json::Value::Eorc(proto::schema::EntityOrCommon {
646                        name,
647                        required: required.unwrap_or(true),
648                    })
649                }
650            };
651
652            proto::schema::TypeJson { value: Some(value) }
653        }
654    }
655
656    #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
657    #[schema(as = schema::EntityType)]
658    #[serde(rename_all = "camelCase", default)]
659    pub struct EntityType {
660        #[serde(skip_serializing_if = "Option::is_none")]
661        pub member_of_types: Option<Vec<String>>,
662        #[serde(skip_serializing_if = "Option::is_none")]
663        pub shape: Option<TypeJson>,
664        #[serde(skip_serializing_if = "Option::is_none")]
665        pub tags: Option<TypeJson>,
666        #[serde(rename = "enum")]
667        #[serde(skip_serializing_if = "Option::is_none")]
668        pub r#enum: Option<Vec<String>>,
669        #[serde(skip_serializing_if = "HashMap::is_empty")]
670        pub annotations: HashMap<String, String>,
671    }
672
673    impl From<proto::schema::EntityType> for EntityType {
674        fn from(value: proto::schema::EntityType) -> Self {
675            Self {
676                member_of_types: match value.member_of_types.is_empty() {
677                    true => None,
678                    false => Some(value.member_of_types),
679                },
680                shape: value.shape.map(TypeJson::from),
681                tags: value.tags.map(TypeJson::from),
682                r#enum: match value.enums.is_empty() {
683                    true => None,
684                    false => Some(value.enums),
685                },
686                annotations: value.annotations,
687            }
688        }
689    }
690
691    impl From<EntityType> for proto::schema::EntityType {
692        fn from(val: EntityType) -> Self {
693            proto::schema::EntityType {
694                member_of_types: val.member_of_types.unwrap_or_default(),
695                shape: val.shape.map(|s| s.into()),
696                tags: val.tags.map(|s| s.into()),
697                enums: val.r#enum.unwrap_or_default(),
698                annotations: val.annotations,
699            }
700        }
701    }
702
703    #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
704    #[schema(as = schema::AppliesTo)]
705    #[serde(rename_all = "camelCase", default)]
706    pub struct AppliesTo {
707        principal_types: Vec<String>,
708        resource_types: Vec<String>,
709        #[serde(skip_serializing_if = "Option::is_none")]
710        context: Option<TypeJson>,
711    }
712
713    impl From<proto::schema::AppliesTo> for AppliesTo {
714        fn from(value: proto::schema::AppliesTo) -> Self {
715            Self {
716                principal_types: value.principal_types,
717                resource_types: value.resource_types,
718                context: value.context.map(TypeJson::from),
719            }
720        }
721    }
722
723    impl From<AppliesTo> for proto::schema::AppliesTo {
724        fn from(val: AppliesTo) -> Self {
725            proto::schema::AppliesTo {
726                principal_types: val.principal_types,
727                resource_types: val.resource_types,
728                context: val.context.map(|c| c.into()),
729            }
730        }
731    }
732
733    #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
734    #[schema(as = schema::Action)]
735    #[serde(rename_all = "camelCase", default)]
736    pub struct Action {
737        #[serde(skip_serializing_if = "Option::is_none")]
738        member_of: Option<Vec<EntityUid>>,
739        #[serde(skip_serializing_if = "Option::is_none")]
740        applies_to: Option<AppliesTo>,
741        #[serde(skip_serializing_if = "HashMap::is_empty")]
742        annotations: HashMap<String, String>,
743    }
744
745    impl From<proto::schema::Action> for Action {
746        fn from(value: proto::schema::Action) -> Self {
747            Self {
748                member_of: match value.member_of.is_empty() {
749                    true => None,
750                    false => Some(value.member_of.into_iter().map(EntityUid::from).collect()),
751                },
752                applies_to: value.applies_to.map(AppliesTo::from),
753                annotations: value.annotations,
754            }
755        }
756    }
757
758    impl From<Action> for proto::schema::Action {
759        fn from(val: Action) -> Self {
760            proto::schema::Action {
761                member_of: val
762                    .member_of
763                    .unwrap_or_default()
764                    .into_iter()
765                    .map(Into::into)
766                    .collect(),
767                applies_to: val.applies_to.map(|a| a.into()),
768                annotations: val.annotations,
769            }
770        }
771    }
772
773    #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
774    #[schema(as = schema::Namespace)]
775    #[serde(rename_all = "camelCase", default)]
776    pub struct Namespace {
777        pub entity_types: HashMap<String, EntityType>,
778        pub actions: HashMap<String, Action>,
779        #[serde(skip_serializing_if = "Option::is_none")]
780        pub common_types: Option<HashMap<String, TypeJson>>,
781    }
782
783    impl From<proto::schema::Namespace> for Namespace {
784        fn from(value: proto::schema::Namespace) -> Self {
785            let common_types = {
786                if value.common_types.is_empty() {
787                    None
788                } else {
789                    Some(
790                        value
791                            .common_types
792                            .into_iter()
793                            .map(|(k, v)| (k, TypeJson::from(v)))
794                            .collect(),
795                    )
796                }
797            };
798
799            Self {
800                entity_types: value
801                    .entity_types
802                    .into_iter()
803                    .map(|(k, v)| (k, EntityType::from(v)))
804                    .collect(),
805                actions: value
806                    .actions
807                    .into_iter()
808                    .map(|(k, v)| (k, Action::from(v)))
809                    .collect(),
810                common_types,
811            }
812        }
813    }
814
815    impl From<Namespace> for proto::schema::Namespace {
816        fn from(val: Namespace) -> Self {
817            let common_types = {
818                if let Some(common_types) = val.common_types {
819                    common_types
820                        .into_iter()
821                        .map(|(k, v)| (k, v.into()))
822                        .collect()
823                } else {
824                    HashMap::new()
825                }
826            };
827
828            proto::schema::Namespace {
829                entity_types: val
830                    .entity_types
831                    .into_iter()
832                    .map(|(k, v)| (k, v.into()))
833                    .collect(),
834                actions: val
835                    .actions
836                    .into_iter()
837                    .map(|(k, v)| (k, v.into()))
838                    .collect(),
839                common_types,
840            }
841        }
842    }
843}
844
845#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
846#[serde(default)]
847pub struct Schema(pub HashMap<String, schema::Namespace>);
848
849impl TryInto<cedar_policy::Schema> for Schema {
850    type Error = cedar_policy::SchemaError;
851
852    fn try_into(self) -> Result<cedar_policy::Schema, Self::Error> {
853        let value = serde_json::to_value(&self).unwrap();
854        let schema = cedar_policy::Schema::from_json_value(value)?;
855        Ok(schema)
856    }
857}
858
859impl From<proto::Schema> for Schema {
860    fn from(value: proto::Schema) -> Self {
861        Self(value.ns.into_iter().map(|(k, v)| (k, v.into())).collect())
862    }
863}
864
865impl From<Schema> for proto::Schema {
866    fn from(val: Schema) -> Self {
867        proto::Schema {
868            ns: val.0.into_iter().map(|(k, v)| (k, v.into())).collect(),
869        }
870    }
871}
872
873#[derive(Debug, Default, Clone, Eq, Hash, PartialEq, Serialize, Deserialize, ToSchema)]
874pub enum SlotId {
875    #[default]
876    #[serde(rename = "?principal")]
877    Principal,
878    #[serde(rename = "?resource")]
879    Resource,
880}
881
882impl From<String> for SlotId {
883    fn from(value: String) -> Self {
884        if "?principal".eq(&value) {
885            Self::Principal
886        } else {
887            Self::Resource
888        }
889    }
890}
891
892impl From<cedar_policy::SlotId> for SlotId {
893    fn from(value: cedar_policy::SlotId) -> Self {
894        if "?principal".eq(&value.to_string()) {
895            Self::Principal
896        } else {
897            Self::Resource
898        }
899    }
900}
901
902impl From<SlotId> for cedar_policy::SlotId {
903    fn from(val: SlotId) -> Self {
904        match val {
905            SlotId::Principal => cedar_policy::SlotId::principal(),
906            SlotId::Resource => cedar_policy::SlotId::resource(),
907        }
908    }
909}
910
911impl From<proto::SlotId> for SlotId {
912    fn from(value: proto::SlotId) -> Self {
913        match value {
914            proto::SlotId::Principal => Self::Principal,
915            proto::SlotId::Resource => Self::Resource,
916        }
917    }
918}
919
920impl From<SlotId> for proto::SlotId {
921    fn from(val: SlotId) -> Self {
922        match val {
923            SlotId::Principal => proto::SlotId::Principal,
924            SlotId::Resource => proto::SlotId::Resource,
925        }
926    }
927}
928
929impl std::fmt::Display for SlotId {
930    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
931        match self {
932            Self::Principal => write!(f, "?principal"),
933            Self::Resource => write!(f, "?resource"),
934        }
935    }
936}
937
938#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
939pub struct EntityOrSlot {
940    #[serde(skip_serializing_if = "Option::is_none")]
941    entity: Option<EntityUid>,
942    #[serde(skip_serializing_if = "Option::is_none")]
943    slot: Option<SlotId>,
944}
945
946impl From<proto::EntityOrSlot> for EntityOrSlot {
947    fn from(value: proto::EntityOrSlot) -> Self {
948        if let Some(entity) = value.entity {
949            Self {
950                entity: Some(entity.into()),
951                slot: None,
952            }
953        } else {
954            Self {
955                entity: None,
956                slot: Some(value.slot().into()),
957            }
958        }
959    }
960}
961
962impl From<EntityOrSlot> for proto::EntityOrSlot {
963    fn from(val: EntityOrSlot) -> Self {
964        if let Some(entity) = val.entity {
965            proto::EntityOrSlot {
966                entity: Some(entity.into()),
967                slot: 0,
968            }
969        } else {
970            let slot: proto::SlotId = val.slot.unwrap().into();
971            proto::EntityOrSlot {
972                entity: None,
973                slot: slot.into(),
974            }
975        }
976    }
977}
978
979#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
980pub enum PrincipalOperator {
981    #[default]
982    All,
983    #[serde(rename = "==")]
984    Eq,
985    #[serde(rename = "in")]
986    In,
987    #[serde(rename = "is")]
988    Is,
989}
990
991impl From<proto::principal_op::Operator> for PrincipalOperator {
992    fn from(value: proto::principal_op::Operator) -> Self {
993        match value {
994            proto::principal_op::Operator::All => Self::All,
995            proto::principal_op::Operator::Eq => Self::Eq,
996            proto::principal_op::Operator::In => Self::In,
997            proto::principal_op::Operator::Is => Self::Is,
998        }
999    }
1000}
1001
1002impl From<PrincipalOperator> for proto::principal_op::Operator {
1003    fn from(val: PrincipalOperator) -> Self {
1004        match val {
1005            PrincipalOperator::All => proto::principal_op::Operator::All,
1006            PrincipalOperator::Eq => proto::principal_op::Operator::Eq,
1007            PrincipalOperator::In => proto::principal_op::Operator::In,
1008            PrincipalOperator::Is => proto::principal_op::Operator::Is,
1009        }
1010    }
1011}
1012
1013#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1014pub enum ResourceOperator {
1015    #[default]
1016    All,
1017    #[serde(rename = "==")]
1018    Eq,
1019    #[serde(rename = "in")]
1020    In,
1021    #[serde(rename = "is")]
1022    Is,
1023}
1024
1025impl From<proto::resource_op::Operator> for ResourceOperator {
1026    fn from(value: proto::resource_op::Operator) -> Self {
1027        match value {
1028            proto::resource_op::Operator::All => Self::All,
1029            proto::resource_op::Operator::Eq => Self::Eq,
1030            proto::resource_op::Operator::In => Self::In,
1031            proto::resource_op::Operator::Is => Self::Is,
1032        }
1033    }
1034}
1035
1036impl From<ResourceOperator> for proto::resource_op::Operator {
1037    fn from(val: ResourceOperator) -> Self {
1038        match val {
1039            ResourceOperator::All => proto::resource_op::Operator::All,
1040            ResourceOperator::Eq => proto::resource_op::Operator::Eq,
1041            ResourceOperator::In => proto::resource_op::Operator::In,
1042            ResourceOperator::Is => proto::resource_op::Operator::Is,
1043        }
1044    }
1045}
1046
1047#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1048pub enum ActionOperator {
1049    #[default]
1050    All,
1051    #[serde(rename = "==")]
1052    Eq,
1053    #[serde(rename = "in")]
1054    In,
1055}
1056
1057impl From<proto::action_op::Operator> for ActionOperator {
1058    fn from(value: proto::action_op::Operator) -> Self {
1059        match value {
1060            proto::action_op::Operator::All => Self::All,
1061            proto::action_op::Operator::Eq => Self::Eq,
1062            proto::action_op::Operator::In => Self::In,
1063        }
1064    }
1065}
1066
1067impl From<ActionOperator> for proto::action_op::Operator {
1068    fn from(val: ActionOperator) -> Self {
1069        match val {
1070            ActionOperator::All => proto::action_op::Operator::All,
1071            ActionOperator::Eq => proto::action_op::Operator::Eq,
1072            ActionOperator::In => proto::action_op::Operator::In,
1073        }
1074    }
1075}
1076
1077#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1078#[serde(default)]
1079pub struct PrincipalOp {
1080    op: PrincipalOperator,
1081    #[serde(skip_serializing_if = "Option::is_none")]
1082    entity: Option<EntityUid>,
1083    #[serde(skip_serializing_if = "Option::is_none")]
1084    slot: Option<SlotId>,
1085    #[serde(skip_serializing_if = "Option::is_none")]
1086    entity_type: Option<String>,
1087    #[serde(rename = "in")]
1088    #[serde(skip_serializing_if = "Option::is_none")]
1089    r#in: Option<EntityOrSlot>,
1090}
1091
1092impl From<proto::PrincipalOp> for PrincipalOp {
1093    fn from(value: proto::PrincipalOp) -> Self {
1094        let op = proto::principal_op::Operator::try_from(value.op)
1095            .unwrap()
1096            .into();
1097
1098        match op {
1099            PrincipalOperator::All => Self {
1100                op,
1101                ..Default::default()
1102            },
1103            PrincipalOperator::Is => Self {
1104                op,
1105                entity_type: Some(value.entity_type),
1106                r#in: value.eors.map(|v| v.into()),
1107                ..Default::default()
1108            },
1109            _ => {
1110                if let Some(entity) = value.entity {
1111                    Self {
1112                        op,
1113                        entity: Some(entity.into()),
1114                        ..Default::default()
1115                    }
1116                } else {
1117                    let slot_id = proto::SlotId::try_from(value.slot).unwrap();
1118                    Self {
1119                        op,
1120                        slot: Some(slot_id.into()),
1121                        ..Default::default()
1122                    }
1123                }
1124            }
1125        }
1126    }
1127}
1128
1129impl From<PrincipalOp> for proto::PrincipalOp {
1130    fn from(val: PrincipalOp) -> Self {
1131        let op: proto::principal_op::Operator = val.op.into();
1132
1133        match op {
1134            proto::principal_op::Operator::All => proto::PrincipalOp {
1135                op: op.into(),
1136                ..Default::default()
1137            },
1138            proto::principal_op::Operator::Is => proto::PrincipalOp {
1139                op: op.into(),
1140                entity_type: val.entity_type.unwrap_or_default(),
1141                eors: val.r#in.map(|v| v.into()),
1142                ..Default::default()
1143            },
1144            _ => {
1145                if let Some(entity) = val.entity {
1146                    proto::PrincipalOp {
1147                        op: op.into(),
1148                        entity: Some(entity.into()),
1149                        ..Default::default()
1150                    }
1151                } else {
1152                    let slot: proto::SlotId = val.slot.unwrap().into();
1153                    proto::PrincipalOp {
1154                        op: op.into(),
1155                        slot: slot.into(),
1156                        ..Default::default()
1157                    }
1158                }
1159            }
1160        }
1161    }
1162}
1163
1164#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1165#[serde(default)]
1166pub struct ResourceOp {
1167    op: ResourceOperator,
1168    #[serde(skip_serializing_if = "Option::is_none")]
1169    entity: Option<EntityUid>,
1170    #[serde(skip_serializing_if = "Option::is_none")]
1171    slot: Option<SlotId>,
1172    #[serde(skip_serializing_if = "Option::is_none")]
1173    entity_type: Option<String>,
1174    #[serde(rename = "in")]
1175    #[serde(skip_serializing_if = "Option::is_none")]
1176    r#in: Option<EntityOrSlot>,
1177}
1178
1179impl From<proto::ResourceOp> for ResourceOp {
1180    fn from(value: proto::ResourceOp) -> Self {
1181        let op = proto::resource_op::Operator::try_from(value.op)
1182            .unwrap()
1183            .into();
1184
1185        match op {
1186            ResourceOperator::All => Self {
1187                op,
1188                ..Default::default()
1189            },
1190            ResourceOperator::Is => Self {
1191                op,
1192                entity_type: Some(value.entity_type),
1193                r#in: value.eors.map(|v| v.into()),
1194                ..Default::default()
1195            },
1196            _ => {
1197                if let Some(entity) = value.entity {
1198                    Self {
1199                        op,
1200                        entity: Some(entity.into()),
1201                        ..Default::default()
1202                    }
1203                } else {
1204                    let slot_id = proto::SlotId::try_from(value.slot).unwrap();
1205                    Self {
1206                        op,
1207                        slot: Some(slot_id.into()),
1208                        ..Default::default()
1209                    }
1210                }
1211            }
1212        }
1213    }
1214}
1215
1216impl From<ResourceOp> for proto::ResourceOp {
1217    fn from(val: ResourceOp) -> Self {
1218        let op: proto::resource_op::Operator = val.op.into();
1219
1220        match op {
1221            proto::resource_op::Operator::All => proto::ResourceOp {
1222                op: op.into(),
1223                ..Default::default()
1224            },
1225            proto::resource_op::Operator::Is => proto::ResourceOp {
1226                op: op.into(),
1227                entity_type: val.entity_type.unwrap_or_default(),
1228                eors: val.r#in.map(|v| v.into()),
1229                ..Default::default()
1230            },
1231            _ => {
1232                if let Some(entity) = val.entity {
1233                    proto::ResourceOp {
1234                        op: op.into(),
1235                        entity: Some(entity.into()),
1236                        ..Default::default()
1237                    }
1238                } else {
1239                    let slot: proto::SlotId = val.slot.unwrap().into();
1240                    proto::ResourceOp {
1241                        op: op.into(),
1242                        slot: slot.into(),
1243                        ..Default::default()
1244                    }
1245                }
1246            }
1247        }
1248    }
1249}
1250
1251#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1252#[serde(default)]
1253pub struct ActionOp {
1254    op: ActionOperator,
1255    #[serde(skip_serializing_if = "Option::is_none")]
1256    entity: Option<EntityUid>,
1257    #[serde(skip_serializing_if = "Option::is_none")]
1258    entities: Option<Vec<EntityUid>>,
1259}
1260
1261impl From<proto::ActionOp> for ActionOp {
1262    fn from(value: proto::ActionOp) -> Self {
1263        let op = proto::action_op::Operator::try_from(value.op)
1264            .unwrap()
1265            .into();
1266
1267        match op {
1268            ActionOperator::All => Self {
1269                op,
1270                ..Default::default()
1271            },
1272            _ => {
1273                if let Some(entity) = value.entity {
1274                    Self {
1275                        op,
1276                        entity: Some(entity.into()),
1277                        ..Default::default()
1278                    }
1279                } else {
1280                    Self {
1281                        op,
1282                        entities: Some(value.entities.into_iter().map(|e| e.into()).collect()),
1283                        ..Default::default()
1284                    }
1285                }
1286            }
1287        }
1288    }
1289}
1290
1291impl From<ActionOp> for proto::ActionOp {
1292    fn from(val: ActionOp) -> Self {
1293        let op: proto::action_op::Operator = val.op.into();
1294
1295        match op {
1296            proto::action_op::Operator::All => proto::ActionOp {
1297                op: op.into(),
1298                ..Default::default()
1299            },
1300            _ => {
1301                if let Some(entity) = val.entity {
1302                    proto::ActionOp {
1303                        op: op.into(),
1304                        entity: Some(entity.into()),
1305                        ..Default::default()
1306                    }
1307                } else {
1308                    proto::ActionOp {
1309                        op: op.into(),
1310                        entities: val
1311                            .entities
1312                            .unwrap()
1313                            .into_iter()
1314                            .map(|e| e.into())
1315                            .collect(),
1316                        ..Default::default()
1317                    }
1318                }
1319            }
1320        }
1321    }
1322}
1323
1324#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1325pub struct SetExpr {
1326    #[serde(rename = "Set")]
1327    #[schema(no_recursion)]
1328    set: Vec<JsonExpr>,
1329}
1330
1331impl From<proto::json_expr::value_expr::Set> for SetExpr {
1332    fn from(value: proto::json_expr::value_expr::Set) -> Self {
1333        Self {
1334            set: value.set.into_iter().map(JsonExpr::from).collect(),
1335        }
1336    }
1337}
1338
1339impl From<SetExpr> for proto::json_expr::value_expr::Set {
1340    fn from(val: SetExpr) -> Self {
1341        proto::json_expr::value_expr::Set {
1342            set: val.set.into_iter().map(|e| e.into()).collect(),
1343        }
1344    }
1345}
1346
1347#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1348pub struct RecordExpr {
1349    #[serde(rename = "Record")]
1350    #[schema(no_recursion)]
1351    record: HashMap<String, JsonExpr>,
1352}
1353
1354impl From<proto::json_expr::value_expr::Record> for RecordExpr {
1355    fn from(value: proto::json_expr::value_expr::Record) -> Self {
1356        Self {
1357            record: value
1358                .record
1359                .into_iter()
1360                .map(|(k, v)| (k, JsonExpr::from(v)))
1361                .collect(),
1362        }
1363    }
1364}
1365
1366impl From<RecordExpr> for proto::json_expr::value_expr::Record {
1367    fn from(val: RecordExpr) -> Self {
1368        proto::json_expr::value_expr::Record {
1369            record: val.record.into_iter().map(|(k, v)| (k, v.into())).collect(),
1370        }
1371    }
1372}
1373
1374#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1375#[serde(untagged)]
1376pub enum ValueExpr {
1377    String(String),
1378    Number(i64),
1379    Boolean(bool),
1380    Set(SetExpr),
1381    Record(RecordExpr),
1382    EntityUidEscape(EntityUidEscape),
1383}
1384
1385impl Default for ValueExpr {
1386    fn default() -> Self {
1387        ValueExpr::String(String::default())
1388    }
1389}
1390
1391impl From<proto::json_expr::ValueExpr> for ValueExpr {
1392    fn from(value: proto::json_expr::ValueExpr) -> Self {
1393        match value.value.unwrap() {
1394            proto::json_expr::value_expr::Value::S(s) => ValueExpr::String(s),
1395            proto::json_expr::value_expr::Value::I(n) => ValueExpr::Number(n),
1396            proto::json_expr::value_expr::Value::B(b) => ValueExpr::Boolean(b),
1397            proto::json_expr::value_expr::Value::Set(s) => ValueExpr::Set(SetExpr {
1398                set: s.set.into_iter().map(JsonExpr::from).collect(),
1399            }),
1400            proto::json_expr::value_expr::Value::Record(r) => ValueExpr::Record(RecordExpr {
1401                record: r
1402                    .record
1403                    .into_iter()
1404                    .map(|(k, v)| (k, JsonExpr::from(v)))
1405                    .collect(),
1406            }),
1407            proto::json_expr::value_expr::Value::Euide(e) => {
1408                ValueExpr::EntityUidEscape(EntityUidEscape::from(e))
1409            }
1410        }
1411    }
1412}
1413
1414impl From<ValueExpr> for proto::json_expr::ValueExpr {
1415    fn from(val: ValueExpr) -> Self {
1416        proto::json_expr::ValueExpr {
1417            value: Some(match val {
1418                ValueExpr::String(s) => proto::json_expr::value_expr::Value::S(s),
1419                ValueExpr::Number(n) => proto::json_expr::value_expr::Value::I(n),
1420                ValueExpr::Boolean(b) => proto::json_expr::value_expr::Value::B(b),
1421                ValueExpr::Set(s) => {
1422                    proto::json_expr::value_expr::Value::Set(proto::json_expr::value_expr::Set {
1423                        set: s.set.into_iter().map(|e| e.into()).collect(),
1424                    })
1425                }
1426                ValueExpr::Record(r) => proto::json_expr::value_expr::Value::Record(
1427                    proto::json_expr::value_expr::Record {
1428                        record: r.record.into_iter().map(|(k, v)| (k, v.into())).collect(),
1429                    },
1430                ),
1431                ValueExpr::EntityUidEscape(e) => {
1432                    proto::json_expr::value_expr::Value::Euide(e.into())
1433                }
1434            }),
1435        }
1436    }
1437}
1438
1439#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1440pub enum VarValue {
1441    #[default]
1442    #[serde(rename = "principal")]
1443    Principal,
1444    #[serde(rename = "action")]
1445    Action,
1446    #[serde(rename = "resource")]
1447    Resource,
1448    #[serde(rename = "context")]
1449    Context,
1450}
1451
1452impl From<proto::json_expr::VarValue> for VarValue {
1453    fn from(value: proto::json_expr::VarValue) -> Self {
1454        match value {
1455            proto::json_expr::VarValue::Principal => VarValue::Principal,
1456            proto::json_expr::VarValue::Action => VarValue::Action,
1457            proto::json_expr::VarValue::Resource => VarValue::Resource,
1458            proto::json_expr::VarValue::Context => VarValue::Context,
1459        }
1460    }
1461}
1462
1463impl From<VarValue> for proto::json_expr::VarValue {
1464    fn from(val: VarValue) -> Self {
1465        match val {
1466            VarValue::Principal => proto::json_expr::VarValue::Principal,
1467            VarValue::Action => proto::json_expr::VarValue::Action,
1468            VarValue::Resource => proto::json_expr::VarValue::Resource,
1469            VarValue::Context => proto::json_expr::VarValue::Context,
1470        }
1471    }
1472}
1473
1474#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1475pub struct HasExpr {
1476    #[schema(no_recursion)]
1477    left: JsonExpr,
1478    attr: String,
1479}
1480
1481impl From<proto::json_expr::HasExpr> for HasExpr {
1482    fn from(value: proto::json_expr::HasExpr) -> Self {
1483        Self {
1484            left: JsonExpr::from(*value.left.unwrap()),
1485            attr: value.attr,
1486        }
1487    }
1488}
1489
1490impl From<HasExpr> for proto::json_expr::HasExpr {
1491    fn from(val: HasExpr) -> Self {
1492        proto::json_expr::HasExpr {
1493            left: Some(::prost::alloc::boxed::Box::new(val.left.into())),
1494            attr: val.attr,
1495        }
1496    }
1497}
1498
1499#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1500pub struct BinaryExpr {
1501    #[schema(no_recursion)]
1502    left: JsonExpr,
1503    #[schema(no_recursion)]
1504    right: JsonExpr,
1505}
1506
1507impl From<proto::json_expr::BinaryExpr> for BinaryExpr {
1508    fn from(value: proto::json_expr::BinaryExpr) -> Self {
1509        Self {
1510            left: JsonExpr::from(*value.left.unwrap()),
1511            right: JsonExpr::from(*value.right.unwrap()),
1512        }
1513    }
1514}
1515
1516impl From<BinaryExpr> for proto::json_expr::BinaryExpr {
1517    fn from(val: BinaryExpr) -> Self {
1518        proto::json_expr::BinaryExpr {
1519            left: Some(::prost::alloc::boxed::Box::new(val.left.into())),
1520            right: Some(::prost::alloc::boxed::Box::new(val.right.into())),
1521        }
1522    }
1523}
1524
1525#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1526pub struct NegExpr {
1527    #[schema(no_recursion)]
1528    arg: JsonExpr,
1529}
1530
1531impl From<proto::json_expr::NegExpr> for NegExpr {
1532    fn from(value: proto::json_expr::NegExpr) -> Self {
1533        Self {
1534            arg: JsonExpr::from(*value.arg.unwrap()),
1535        }
1536    }
1537}
1538
1539impl From<NegExpr> for proto::json_expr::NegExpr {
1540    fn from(val: NegExpr) -> Self {
1541        proto::json_expr::NegExpr {
1542            arg: Some(::prost::alloc::boxed::Box::new(val.arg.into())),
1543        }
1544    }
1545}
1546
1547#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1548pub struct IsExpr {
1549    #[schema(no_recursion)]
1550    left: JsonExpr,
1551    entity_type: String,
1552}
1553
1554impl From<proto::json_expr::IsExpr> for IsExpr {
1555    fn from(value: proto::json_expr::IsExpr) -> Self {
1556        Self {
1557            left: JsonExpr::from(*value.left.unwrap()),
1558            entity_type: value.entity_type,
1559        }
1560    }
1561}
1562
1563impl From<IsExpr> for proto::json_expr::IsExpr {
1564    fn from(val: IsExpr) -> Self {
1565        proto::json_expr::IsExpr {
1566            left: Some(::prost::alloc::boxed::Box::new(val.left.into())),
1567            entity_type: val.entity_type,
1568        }
1569    }
1570}
1571
1572#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1573pub enum PatternElem {
1574    Literal(String),
1575    Wildcard,
1576}
1577
1578#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1579pub struct LikeExpr {
1580    #[schema(no_recursion)]
1581    left: JsonExpr,
1582    pattern: Vec<PatternElem>,
1583}
1584
1585impl From<proto::json_expr::LikeExpr> for LikeExpr {
1586    fn from(value: proto::json_expr::LikeExpr) -> Self {
1587        Self {
1588            left: JsonExpr::from(*value.left.unwrap()),
1589            pattern: value
1590                .pattern
1591                .into_iter()
1592                .map(|e| match e.value.unwrap() {
1593                    proto::json_expr::pattern_elem::Value::Literal(s) => PatternElem::Literal(s),
1594                    proto::json_expr::pattern_elem::Value::Wildcard(_) => PatternElem::Wildcard,
1595                })
1596                .collect(),
1597        }
1598    }
1599}
1600
1601impl From<LikeExpr> for proto::json_expr::LikeExpr {
1602    fn from(val: LikeExpr) -> Self {
1603        let pattern = val
1604            .pattern
1605            .into_iter()
1606            .map(|e| proto::json_expr::PatternElem {
1607                value: Some(match e {
1608                    PatternElem::Literal(s) => proto::json_expr::pattern_elem::Value::Literal(s),
1609                    PatternElem::Wildcard => proto::json_expr::pattern_elem::Value::Wildcard(true),
1610                }),
1611            })
1612            .collect();
1613
1614        proto::json_expr::LikeExpr {
1615            left: Some(::prost::alloc::boxed::Box::new(val.left.into())),
1616            pattern,
1617        }
1618    }
1619}
1620
1621#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1622pub struct IfThenElseExpr {
1623    #[serde(rename = "if")]
1624    #[schema(no_recursion)]
1625    pub r#if: JsonExpr,
1626    #[serde(rename = "then")]
1627    #[schema(no_recursion)]
1628    pub then: JsonExpr,
1629    #[serde(rename = "else")]
1630    #[schema(no_recursion)]
1631    pub r#else: JsonExpr,
1632}
1633
1634impl From<proto::json_expr::IfThenElseExpr> for IfThenElseExpr {
1635    fn from(value: proto::json_expr::IfThenElseExpr) -> Self {
1636        Self {
1637            r#if: JsonExpr::from(*value.r#if.unwrap()),
1638            then: JsonExpr::from(*value.then.unwrap()),
1639            r#else: JsonExpr::from(*value.r#else.unwrap()),
1640        }
1641    }
1642}
1643
1644impl From<IfThenElseExpr> for proto::json_expr::IfThenElseExpr {
1645    fn from(val: IfThenElseExpr) -> Self {
1646        proto::json_expr::IfThenElseExpr {
1647            r#if: Some(Box::new(val.r#if.into())),
1648            then: Some(Box::new(val.then.into())),
1649            r#else: Some(Box::new(val.r#else.into())),
1650        }
1651    }
1652}
1653
1654#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
1655pub enum JsonExpr {
1656    Value(ValueExpr),
1657    Var(VarValue),
1658    Slot(SlotId),
1659
1660    #[serde(rename = "!")]
1661    Bang(Box<NegExpr>),
1662    #[serde(rename = "neg")]
1663    Neg(Box<NegExpr>),
1664    #[serde(rename = "isEmpty")]
1665    IsEmpty(Box<NegExpr>),
1666
1667    #[serde(rename = "==")]
1668    Eq(Box<BinaryExpr>),
1669    #[serde(rename = "!=")]
1670    Neq(Box<BinaryExpr>),
1671    #[serde(rename = "in")]
1672    In(Box<BinaryExpr>),
1673    #[serde(rename = "<")]
1674    Lt(Box<BinaryExpr>),
1675    #[serde(rename = "<=")]
1676    Lte(Box<BinaryExpr>),
1677    #[serde(rename = ">")]
1678    Gt(Box<BinaryExpr>),
1679    #[serde(rename = ">=")]
1680    Gte(Box<BinaryExpr>),
1681    #[serde(rename = "&&")]
1682    And(Box<BinaryExpr>),
1683    #[serde(rename = "||")]
1684    Or(Box<BinaryExpr>),
1685    #[serde(rename = "+")]
1686    Plus(Box<BinaryExpr>),
1687    #[serde(rename = "-")]
1688    Minus(Box<BinaryExpr>),
1689    #[serde(rename = "*")]
1690    Mul(Box<BinaryExpr>),
1691    #[serde(rename = "contains")]
1692    Contains(Box<BinaryExpr>),
1693    #[serde(rename = "containsAll")]
1694    ContainsAll(Box<BinaryExpr>),
1695    #[serde(rename = "containsAny")]
1696    ContainsAny(Box<BinaryExpr>),
1697    #[serde(rename = "hasTag")]
1698    HasTag(Box<BinaryExpr>),
1699    #[serde(rename = "getTag")]
1700    GetTag(Box<BinaryExpr>),
1701
1702    #[serde(rename = ".")]
1703    Dot(Box<HasExpr>),
1704    #[serde(rename = "has")]
1705    Has(Box<HasExpr>),
1706
1707    #[serde(rename = "is")]
1708    Is(Box<IsExpr>),
1709
1710    #[serde(rename = "like")]
1711    Like(Box<LikeExpr>),
1712
1713    #[serde(rename = "if-then-else")]
1714    IfThenElse(Box<IfThenElseExpr>),
1715
1716    #[schema(no_recursion)]
1717    Set(Vec<JsonExpr>),
1718    #[schema(no_recursion)]
1719    Record(HashMap<String, JsonExpr>),
1720
1721    #[serde(rename = "datetime")]
1722    #[schema(no_recursion)]
1723    Datetime(Vec<JsonExpr>),
1724    #[serde(rename = "decimal")]
1725    #[schema(no_recursion)]
1726    Decimal(Vec<JsonExpr>),
1727    #[serde(rename = "duration")]
1728    #[schema(no_recursion)]
1729    Duration(Vec<JsonExpr>),
1730    #[serde(rename = "ip")]
1731    #[schema(no_recursion)]
1732    Ip(Vec<JsonExpr>),
1733
1734    //IP address functions
1735    #[serde(rename = "isIpV4")]
1736    #[schema(no_recursion)]
1737    IsIpV4(Vec<JsonExpr>),
1738    #[serde(rename = "isIpV6")]
1739    #[schema(no_recursion)]
1740    IsIpV6(Vec<JsonExpr>),
1741    #[serde(rename = "isLoopback")]
1742    #[schema(no_recursion)]
1743    IsLoopback(Vec<JsonExpr>),
1744    #[serde(rename = "isMulticast")]
1745    #[schema(no_recursion)]
1746    IsMulticast(Vec<JsonExpr>),
1747    #[serde(rename = "isInRange")]
1748    #[schema(no_recursion)]
1749    IsInRange(Vec<JsonExpr>),
1750
1751    //Datetime functions
1752    #[serde(rename = "offset")]
1753    #[schema(no_recursion)]
1754    Offset(Vec<JsonExpr>),
1755    #[serde(rename = "durationSince")]
1756    #[schema(no_recursion)]
1757    DurationSince(Vec<JsonExpr>),
1758    #[serde(rename = "toDate")]
1759    #[schema(no_recursion)]
1760    ToDate(Vec<JsonExpr>),
1761    #[serde(rename = "toTime")]
1762    #[schema(no_recursion)]
1763    ToTime(Vec<JsonExpr>),
1764    #[serde(rename = "toMilliseconds")]
1765    #[schema(no_recursion)]
1766    ToMilliseconds(Vec<JsonExpr>),
1767    #[serde(rename = "toSeconds")]
1768    #[schema(no_recursion)]
1769    ToSeconds(Vec<JsonExpr>),
1770    #[serde(rename = "toMinutes")]
1771    #[schema(no_recursion)]
1772    ToMinutes(Vec<JsonExpr>),
1773    #[serde(rename = "toHours")]
1774    #[schema(no_recursion)]
1775    ToHours(Vec<JsonExpr>),
1776    #[serde(rename = "toDays")]
1777    #[schema(no_recursion)]
1778    ToDays(Vec<JsonExpr>),
1779
1780    #[serde(rename = "lessThan")]
1781    #[schema(no_recursion)]
1782    LessThan(Vec<JsonExpr>),
1783    #[serde(rename = "lessThanOrEqual")]
1784    #[schema(no_recursion)]
1785    LessThanOrEqual(Vec<JsonExpr>),
1786    #[serde(rename = "greaterThan")]
1787    #[schema(no_recursion)]
1788    GreaterThan(Vec<JsonExpr>),
1789    #[serde(rename = "greaterThanOrEqual")]
1790    #[schema(no_recursion)]
1791    GreaterThanOrEqual(Vec<JsonExpr>),
1792}
1793
1794impl Default for JsonExpr {
1795    fn default() -> Self {
1796        JsonExpr::Value(ValueExpr::default())
1797    }
1798}
1799
1800impl From<proto::JsonExpr> for JsonExpr {
1801    fn from(value: proto::JsonExpr) -> Self {
1802        match value.expr.unwrap() {
1803            proto::json_expr::Expr::Value(expr) => JsonExpr::Value(expr.into()),
1804            proto::json_expr::Expr::Var(var) => JsonExpr::Var(VarValue::from(
1805                proto::json_expr::VarValue::try_from(var).unwrap(),
1806            )),
1807            proto::json_expr::Expr::Slot(slot_id) => {
1808                JsonExpr::Slot(SlotId::from(proto::SlotId::try_from(slot_id).unwrap()))
1809            }
1810            proto::json_expr::Expr::Neg(expr) => JsonExpr::Neg(Box::new((*expr).into())),
1811            proto::json_expr::Expr::Bang(expr) => JsonExpr::Neg(Box::new((*expr).into())),
1812            proto::json_expr::Expr::IsEmpty(expr) => JsonExpr::IsEmpty(Box::new((*expr).into())),
1813            proto::json_expr::Expr::Eq(expr) => JsonExpr::Eq(Box::new((*expr).into())),
1814            proto::json_expr::Expr::Neq(expr) => JsonExpr::Neq(Box::new((*expr).into())),
1815            proto::json_expr::Expr::In(expr) => JsonExpr::In(Box::new((*expr).into())),
1816            proto::json_expr::Expr::Lt(expr) => JsonExpr::Lt(Box::new((*expr).into())),
1817            proto::json_expr::Expr::Lte(expr) => JsonExpr::Lte(Box::new((*expr).into())),
1818            proto::json_expr::Expr::Gt(expr) => JsonExpr::Gt(Box::new((*expr).into())),
1819            proto::json_expr::Expr::Gte(expr) => JsonExpr::Gte(Box::new((*expr).into())),
1820            proto::json_expr::Expr::And(expr) => JsonExpr::And(Box::new((*expr).into())),
1821            proto::json_expr::Expr::Or(expr) => JsonExpr::Or(Box::new((*expr).into())),
1822            proto::json_expr::Expr::Plus(expr) => JsonExpr::Plus(Box::new((*expr).into())),
1823            proto::json_expr::Expr::Minus(expr) => JsonExpr::Minus(Box::new((*expr).into())),
1824            proto::json_expr::Expr::Mul(expr) => JsonExpr::Mul(Box::new((*expr).into())),
1825            proto::json_expr::Expr::Contains(expr) => JsonExpr::Contains(Box::new((*expr).into())),
1826            proto::json_expr::Expr::ContainsAll(expr) => {
1827                JsonExpr::ContainsAll(Box::new((*expr).into()))
1828            }
1829            proto::json_expr::Expr::ContainsAny(expr) => {
1830                JsonExpr::ContainsAny(Box::new((*expr).into()))
1831            }
1832            proto::json_expr::Expr::HasTag(expr) => JsonExpr::HasTag(Box::new((*expr).into())),
1833            proto::json_expr::Expr::GetTag(expr) => JsonExpr::GetTag(Box::new((*expr).into())),
1834            proto::json_expr::Expr::Has(expr) => JsonExpr::Has(Box::new((*expr).into())),
1835            proto::json_expr::Expr::Dot(expr) => JsonExpr::Dot(Box::new((*expr).into())),
1836            proto::json_expr::Expr::Is(expr) => JsonExpr::Is(Box::new((*expr).into())),
1837            proto::json_expr::Expr::Like(expr) => JsonExpr::Like(Box::new((*expr).into())),
1838            proto::json_expr::Expr::IfThenElse(expr) => {
1839                JsonExpr::IfThenElse(Box::new((*expr).into()))
1840            }
1841            proto::json_expr::Expr::Set(set) => {
1842                JsonExpr::Set(set.set.into_iter().map(JsonExpr::from).collect())
1843            }
1844            proto::json_expr::Expr::Record(record) => JsonExpr::Record(
1845                record
1846                    .record
1847                    .into_iter()
1848                    .map(|(k, v)| (k, JsonExpr::from(v)))
1849                    .collect(),
1850            ),
1851            proto::json_expr::Expr::Datetime(set) => {
1852                JsonExpr::Datetime(set.set.into_iter().map(JsonExpr::from).collect())
1853            }
1854            proto::json_expr::Expr::Decimal(set) => {
1855                JsonExpr::Decimal(set.set.into_iter().map(JsonExpr::from).collect())
1856            }
1857            proto::json_expr::Expr::Duration(set) => {
1858                JsonExpr::Duration(set.set.into_iter().map(JsonExpr::from).collect())
1859            }
1860            proto::json_expr::Expr::Ip(set) => {
1861                JsonExpr::Ip(set.set.into_iter().map(JsonExpr::from).collect())
1862            }
1863            proto::json_expr::Expr::IsIpV4(set) => {
1864                JsonExpr::IsIpV4(set.set.into_iter().map(JsonExpr::from).collect())
1865            }
1866            proto::json_expr::Expr::IsIpV6(set) => {
1867                JsonExpr::IsIpV6(set.set.into_iter().map(JsonExpr::from).collect())
1868            }
1869            proto::json_expr::Expr::IsLoopback(set) => {
1870                JsonExpr::IsLoopback(set.set.into_iter().map(JsonExpr::from).collect())
1871            }
1872            proto::json_expr::Expr::IsMulticast(set) => {
1873                JsonExpr::IsMulticast(set.set.into_iter().map(JsonExpr::from).collect())
1874            }
1875            proto::json_expr::Expr::IsInRange(set) => {
1876                JsonExpr::IsInRange(set.set.into_iter().map(JsonExpr::from).collect())
1877            }
1878            proto::json_expr::Expr::Offset(set) => {
1879                JsonExpr::Offset(set.set.into_iter().map(JsonExpr::from).collect())
1880            }
1881            proto::json_expr::Expr::DurationSince(set) => {
1882                JsonExpr::DurationSince(set.set.into_iter().map(JsonExpr::from).collect())
1883            }
1884            proto::json_expr::Expr::ToDate(set) => {
1885                JsonExpr::ToDate(set.set.into_iter().map(JsonExpr::from).collect())
1886            }
1887            proto::json_expr::Expr::ToTime(set) => {
1888                JsonExpr::ToTime(set.set.into_iter().map(JsonExpr::from).collect())
1889            }
1890            proto::json_expr::Expr::ToMilliseconds(set) => {
1891                JsonExpr::ToMilliseconds(set.set.into_iter().map(JsonExpr::from).collect())
1892            }
1893            proto::json_expr::Expr::ToSeconds(set) => {
1894                JsonExpr::ToSeconds(set.set.into_iter().map(JsonExpr::from).collect())
1895            }
1896            proto::json_expr::Expr::ToMinutes(set) => {
1897                JsonExpr::ToMinutes(set.set.into_iter().map(JsonExpr::from).collect())
1898            }
1899            proto::json_expr::Expr::ToHours(set) => {
1900                JsonExpr::ToHours(set.set.into_iter().map(JsonExpr::from).collect())
1901            }
1902            proto::json_expr::Expr::ToDays(set) => {
1903                JsonExpr::ToDays(set.set.into_iter().map(JsonExpr::from).collect())
1904            }
1905            proto::json_expr::Expr::LessThan(set) => {
1906                JsonExpr::LessThan(set.set.into_iter().map(JsonExpr::from).collect())
1907            }
1908            proto::json_expr::Expr::LessThanOrEqual(set) => {
1909                JsonExpr::LessThanOrEqual(set.set.into_iter().map(JsonExpr::from).collect())
1910            }
1911            proto::json_expr::Expr::GreaterThan(set) => {
1912                JsonExpr::GreaterThan(set.set.into_iter().map(JsonExpr::from).collect())
1913            }
1914            proto::json_expr::Expr::GreaterThanOrEqual(set) => {
1915                JsonExpr::GreaterThanOrEqual(set.set.into_iter().map(JsonExpr::from).collect())
1916            }
1917        }
1918    }
1919}
1920
1921impl From<JsonExpr> for proto::JsonExpr {
1922    fn from(val: JsonExpr) -> Self {
1923        match val {
1924            JsonExpr::Value(value_expr) => proto::JsonExpr {
1925                expr: Some(proto::json_expr::Expr::Value(value_expr.into())),
1926            },
1927            JsonExpr::Var(var) => proto::JsonExpr {
1928                expr: Some(proto::json_expr::Expr::Var(
1929                    Into::<proto::json_expr::VarValue>::into(var) as i32,
1930                )),
1931            },
1932            JsonExpr::Slot(slot_id) => proto::JsonExpr {
1933                expr: Some(proto::json_expr::Expr::Var(
1934                    Into::<proto::SlotId>::into(slot_id).into(),
1935                )),
1936            },
1937            JsonExpr::Neg(expr) => proto::JsonExpr {
1938                expr: Some(proto::json_expr::Expr::Neg(
1939                    ::prost::alloc::boxed::Box::new((*expr).into()),
1940                )),
1941            },
1942            JsonExpr::IsEmpty(expr) => proto::JsonExpr {
1943                expr: Some(proto::json_expr::Expr::IsEmpty(
1944                    ::prost::alloc::boxed::Box::new((*expr).into()),
1945                )),
1946            },
1947            JsonExpr::Bang(expr) => proto::JsonExpr {
1948                expr: Some(proto::json_expr::Expr::Bang(
1949                    ::prost::alloc::boxed::Box::new((*expr).into()),
1950                )),
1951            },
1952            JsonExpr::Eq(expr) => proto::JsonExpr {
1953                expr: Some(proto::json_expr::Expr::Eq(::prost::alloc::boxed::Box::new(
1954                    (*expr).into(),
1955                ))),
1956            },
1957            JsonExpr::Neq(expr) => proto::JsonExpr {
1958                expr: Some(proto::json_expr::Expr::Neq(
1959                    ::prost::alloc::boxed::Box::new((*expr).into()),
1960                )),
1961            },
1962            JsonExpr::In(expr) => proto::JsonExpr {
1963                expr: Some(proto::json_expr::Expr::In(::prost::alloc::boxed::Box::new(
1964                    (*expr).into(),
1965                ))),
1966            },
1967            JsonExpr::Lt(expr) => proto::JsonExpr {
1968                expr: Some(proto::json_expr::Expr::Lt(::prost::alloc::boxed::Box::new(
1969                    (*expr).into(),
1970                ))),
1971            },
1972            JsonExpr::Lte(expr) => proto::JsonExpr {
1973                expr: Some(proto::json_expr::Expr::Lte(
1974                    ::prost::alloc::boxed::Box::new((*expr).into()),
1975                )),
1976            },
1977            JsonExpr::Gt(expr) => proto::JsonExpr {
1978                expr: Some(proto::json_expr::Expr::Gt(::prost::alloc::boxed::Box::new(
1979                    (*expr).into(),
1980                ))),
1981            },
1982            JsonExpr::Gte(expr) => proto::JsonExpr {
1983                expr: Some(proto::json_expr::Expr::Gte(
1984                    ::prost::alloc::boxed::Box::new((*expr).into()),
1985                )),
1986            },
1987            JsonExpr::And(expr) => proto::JsonExpr {
1988                expr: Some(proto::json_expr::Expr::And(
1989                    ::prost::alloc::boxed::Box::new((*expr).into()),
1990                )),
1991            },
1992            JsonExpr::Or(expr) => proto::JsonExpr {
1993                expr: Some(proto::json_expr::Expr::Or(::prost::alloc::boxed::Box::new(
1994                    (*expr).into(),
1995                ))),
1996            },
1997            JsonExpr::Plus(expr) => proto::JsonExpr {
1998                expr: Some(proto::json_expr::Expr::Plus(
1999                    ::prost::alloc::boxed::Box::new((*expr).into()),
2000                )),
2001            },
2002            JsonExpr::Minus(expr) => proto::JsonExpr {
2003                expr: Some(proto::json_expr::Expr::Minus(
2004                    ::prost::alloc::boxed::Box::new((*expr).into()),
2005                )),
2006            },
2007            JsonExpr::Mul(expr) => proto::JsonExpr {
2008                expr: Some(proto::json_expr::Expr::Mul(
2009                    ::prost::alloc::boxed::Box::new((*expr).into()),
2010                )),
2011            },
2012            JsonExpr::Contains(expr) => proto::JsonExpr {
2013                expr: Some(proto::json_expr::Expr::Contains(
2014                    ::prost::alloc::boxed::Box::new((*expr).into()),
2015                )),
2016            },
2017            JsonExpr::ContainsAll(expr) => proto::JsonExpr {
2018                expr: Some(proto::json_expr::Expr::ContainsAll(
2019                    ::prost::alloc::boxed::Box::new((*expr).into()),
2020                )),
2021            },
2022            JsonExpr::ContainsAny(expr) => proto::JsonExpr {
2023                expr: Some(proto::json_expr::Expr::ContainsAny(
2024                    ::prost::alloc::boxed::Box::new((*expr).into()),
2025                )),
2026            },
2027            JsonExpr::HasTag(expr) => proto::JsonExpr {
2028                expr: Some(proto::json_expr::Expr::HasTag(
2029                    ::prost::alloc::boxed::Box::new((*expr).into()),
2030                )),
2031            },
2032            JsonExpr::GetTag(expr) => proto::JsonExpr {
2033                expr: Some(proto::json_expr::Expr::GetTag(
2034                    ::prost::alloc::boxed::Box::new((*expr).into()),
2035                )),
2036            },
2037            JsonExpr::Has(expr) => proto::JsonExpr {
2038                expr: Some(proto::json_expr::Expr::Has(
2039                    ::prost::alloc::boxed::Box::new((*expr).into()),
2040                )),
2041            },
2042            JsonExpr::Dot(expr) => proto::JsonExpr {
2043                expr: Some(proto::json_expr::Expr::Dot(
2044                    ::prost::alloc::boxed::Box::new((*expr).into()),
2045                )),
2046            },
2047            JsonExpr::Is(expr) => proto::JsonExpr {
2048                expr: Some(proto::json_expr::Expr::Is(::prost::alloc::boxed::Box::new(
2049                    (*expr).into(),
2050                ))),
2051            },
2052            JsonExpr::Like(expr) => proto::JsonExpr {
2053                expr: Some(proto::json_expr::Expr::Like(
2054                    ::prost::alloc::boxed::Box::new((*expr).into()),
2055                )),
2056            },
2057            JsonExpr::IfThenElse(expr) => proto::JsonExpr {
2058                expr: Some(proto::json_expr::Expr::IfThenElse(
2059                    ::prost::alloc::boxed::Box::new((*expr).into()),
2060                )),
2061            },
2062            JsonExpr::Set(expr) => proto::JsonExpr {
2063                expr: Some(proto::json_expr::Expr::Set(proto::json_expr::Set {
2064                    set: expr.into_iter().map(|v| v.into()).collect(),
2065                })),
2066            },
2067            JsonExpr::Record(expr) => proto::JsonExpr {
2068                expr: Some(proto::json_expr::Expr::Record(proto::json_expr::Record {
2069                    record: expr.into_iter().map(|(k, v)| (k, v.into())).collect(),
2070                })),
2071            },
2072            JsonExpr::Datetime(expr) => proto::JsonExpr {
2073                expr: Some(proto::json_expr::Expr::Datetime(proto::json_expr::Set {
2074                    set: expr.into_iter().map(|v| v.into()).collect(),
2075                })),
2076            },
2077            JsonExpr::Decimal(expr) => proto::JsonExpr {
2078                expr: Some(proto::json_expr::Expr::Decimal(proto::json_expr::Set {
2079                    set: expr.into_iter().map(|v| v.into()).collect(),
2080                })),
2081            },
2082            JsonExpr::Duration(expr) => proto::JsonExpr {
2083                expr: Some(proto::json_expr::Expr::Duration(proto::json_expr::Set {
2084                    set: expr.into_iter().map(|v| v.into()).collect(),
2085                })),
2086            },
2087            JsonExpr::Ip(expr) => proto::JsonExpr {
2088                expr: Some(proto::json_expr::Expr::Ip(proto::json_expr::Set {
2089                    set: expr.into_iter().map(|v| v.into()).collect(),
2090                })),
2091            },
2092            JsonExpr::IsIpV4(expr) => proto::JsonExpr {
2093                expr: Some(proto::json_expr::Expr::IsIpV4(proto::json_expr::Set {
2094                    set: expr.into_iter().map(|v| v.into()).collect(),
2095                })),
2096            },
2097            JsonExpr::IsIpV6(expr) => proto::JsonExpr {
2098                expr: Some(proto::json_expr::Expr::IsIpV6(proto::json_expr::Set {
2099                    set: expr.into_iter().map(|v| v.into()).collect(),
2100                })),
2101            },
2102            JsonExpr::IsLoopback(expr) => proto::JsonExpr {
2103                expr: Some(proto::json_expr::Expr::IsLoopback(proto::json_expr::Set {
2104                    set: expr.into_iter().map(|v| v.into()).collect(),
2105                })),
2106            },
2107            JsonExpr::IsMulticast(expr) => proto::JsonExpr {
2108                expr: Some(proto::json_expr::Expr::IsMulticast(proto::json_expr::Set {
2109                    set: expr.into_iter().map(|v| v.into()).collect(),
2110                })),
2111            },
2112            JsonExpr::IsInRange(expr) => proto::JsonExpr {
2113                expr: Some(proto::json_expr::Expr::IsInRange(proto::json_expr::Set {
2114                    set: expr.into_iter().map(|v| v.into()).collect(),
2115                })),
2116            },
2117            JsonExpr::Offset(expr) => proto::JsonExpr {
2118                expr: Some(proto::json_expr::Expr::Offset(proto::json_expr::Set {
2119                    set: expr.into_iter().map(|v| v.into()).collect(),
2120                })),
2121            },
2122            JsonExpr::DurationSince(expr) => proto::JsonExpr {
2123                expr: Some(proto::json_expr::Expr::DurationSince(
2124                    proto::json_expr::Set {
2125                        set: expr.into_iter().map(|v| v.into()).collect(),
2126                    },
2127                )),
2128            },
2129            JsonExpr::ToDate(expr) => proto::JsonExpr {
2130                expr: Some(proto::json_expr::Expr::ToDate(proto::json_expr::Set {
2131                    set: expr.into_iter().map(|v| v.into()).collect(),
2132                })),
2133            },
2134            JsonExpr::ToTime(expr) => proto::JsonExpr {
2135                expr: Some(proto::json_expr::Expr::ToTime(proto::json_expr::Set {
2136                    set: expr.into_iter().map(|v| v.into()).collect(),
2137                })),
2138            },
2139            JsonExpr::ToMilliseconds(expr) => proto::JsonExpr {
2140                expr: Some(proto::json_expr::Expr::ToMilliseconds(
2141                    proto::json_expr::Set {
2142                        set: expr.into_iter().map(|v| v.into()).collect(),
2143                    },
2144                )),
2145            },
2146            JsonExpr::ToSeconds(expr) => proto::JsonExpr {
2147                expr: Some(proto::json_expr::Expr::ToSeconds(proto::json_expr::Set {
2148                    set: expr.into_iter().map(|v| v.into()).collect(),
2149                })),
2150            },
2151            JsonExpr::ToMinutes(expr) => proto::JsonExpr {
2152                expr: Some(proto::json_expr::Expr::ToMinutes(proto::json_expr::Set {
2153                    set: expr.into_iter().map(|v| v.into()).collect(),
2154                })),
2155            },
2156            JsonExpr::ToHours(expr) => proto::JsonExpr {
2157                expr: Some(proto::json_expr::Expr::ToHours(proto::json_expr::Set {
2158                    set: expr.into_iter().map(|v| v.into()).collect(),
2159                })),
2160            },
2161            JsonExpr::ToDays(expr) => proto::JsonExpr {
2162                expr: Some(proto::json_expr::Expr::ToDays(proto::json_expr::Set {
2163                    set: expr.into_iter().map(|v| v.into()).collect(),
2164                })),
2165            },
2166            JsonExpr::LessThan(expr) => proto::JsonExpr {
2167                expr: Some(proto::json_expr::Expr::LessThan(proto::json_expr::Set {
2168                    set: expr.into_iter().map(|v| v.into()).collect(),
2169                })),
2170            },
2171            JsonExpr::LessThanOrEqual(expr) => proto::JsonExpr {
2172                expr: Some(proto::json_expr::Expr::LessThanOrEqual(
2173                    proto::json_expr::Set {
2174                        set: expr.into_iter().map(|v| v.into()).collect(),
2175                    },
2176                )),
2177            },
2178            JsonExpr::GreaterThan(expr) => proto::JsonExpr {
2179                expr: Some(proto::json_expr::Expr::GreaterThan(proto::json_expr::Set {
2180                    set: expr.into_iter().map(|v| v.into()).collect(),
2181                })),
2182            },
2183            JsonExpr::GreaterThanOrEqual(expr) => proto::JsonExpr {
2184                expr: Some(proto::json_expr::Expr::GreaterThanOrEqual(
2185                    proto::json_expr::Set {
2186                        set: expr.into_iter().map(|v| v.into()).collect(),
2187                    },
2188                )),
2189            },
2190        }
2191    }
2192}
2193
2194#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2195pub enum ConditionKind {
2196    #[default]
2197    #[serde(rename = "when")]
2198    When,
2199    #[serde(rename = "unless")]
2200    Unless,
2201}
2202
2203impl From<proto::ConditionKind> for ConditionKind {
2204    fn from(value: proto::ConditionKind) -> Self {
2205        match value {
2206            proto::ConditionKind::When => ConditionKind::When,
2207            proto::ConditionKind::Unless => ConditionKind::Unless,
2208        }
2209    }
2210}
2211
2212impl From<ConditionKind> for proto::ConditionKind {
2213    fn from(val: ConditionKind) -> Self {
2214        match val {
2215            ConditionKind::When => proto::ConditionKind::When,
2216            ConditionKind::Unless => proto::ConditionKind::Unless,
2217        }
2218    }
2219}
2220
2221#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2222pub struct Condition {
2223    kind: ConditionKind,
2224    body: JsonExpr,
2225}
2226
2227impl From<proto::Condition> for Condition {
2228    fn from(value: proto::Condition) -> Self {
2229        Self {
2230            kind: value.kind().into(),
2231            body: value.body.unwrap().into(),
2232        }
2233    }
2234}
2235
2236impl From<Condition> for proto::Condition {
2237    fn from(val: Condition) -> Self {
2238        proto::Condition {
2239            kind: Into::<proto::ConditionKind>::into(val.kind) as i32,
2240            body: Some(val.body.into()),
2241        }
2242    }
2243}
2244
2245#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2246pub enum PolicyEffect {
2247    #[default]
2248    #[serde(rename = "permit")]
2249    Permit,
2250    #[serde(rename = "forbid")]
2251    Forbid,
2252}
2253
2254impl From<proto::Effect> for PolicyEffect {
2255    fn from(value: proto::Effect) -> Self {
2256        match value {
2257            proto::Effect::Permit => PolicyEffect::Permit,
2258            proto::Effect::Forbid => PolicyEffect::Forbid,
2259        }
2260    }
2261}
2262
2263impl From<PolicyEffect> for proto::Effect {
2264    fn from(val: PolicyEffect) -> Self {
2265        match val {
2266            PolicyEffect::Permit => proto::Effect::Permit,
2267            PolicyEffect::Forbid => proto::Effect::Forbid,
2268        }
2269    }
2270}
2271
2272#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2273#[serde(default)]
2274pub struct Policy {
2275    pub effect: PolicyEffect,
2276    pub principal: PrincipalOp,
2277    pub action: ActionOp,
2278    pub resource: ResourceOp,
2279    pub conditions: Vec<Condition>,
2280    #[serde(skip_serializing_if = "HashMap::is_empty")]
2281    pub annotations: HashMap<String, Option<String>>,
2282}
2283
2284impl Policy {
2285    pub fn to_cedar(
2286        &self,
2287        policy_id: PolicyId,
2288    ) -> Result<cedar_policy::Policy, cedar_policy::PolicyFromJsonError> {
2289        let json = serde_json::to_value(self).unwrap();
2290        cedar_policy::Policy::from_json(Some(policy_id.into()), json)
2291    }
2292}
2293
2294impl From<proto::Policy> for Policy {
2295    fn from(value: proto::Policy) -> Self {
2296        Self {
2297            effect: value.effect().into(),
2298            principal: value.principal.unwrap().into(),
2299            action: value.action.unwrap().into(),
2300            resource: value.resource.unwrap().into(),
2301            conditions: value
2302                .conditions
2303                .into_iter()
2304                .map(|c| c.into())
2305                .collect::<Vec<Condition>>(),
2306            annotations: value
2307                .annotations
2308                .into_iter()
2309                .map(|(k, v)| (k, Some(v)))
2310                .collect(),
2311        }
2312    }
2313}
2314
2315impl From<Policy> for proto::Policy {
2316    fn from(val: Policy) -> Self {
2317        proto::Policy {
2318            effect: Into::<proto::Effect>::into(val.effect) as i32,
2319            principal: Some(val.principal.into()),
2320            action: Some(val.action.into()),
2321            resource: Some(val.resource.into()),
2322            conditions: val.conditions.into_iter().map(|c| c.into()).collect(),
2323            annotations: val
2324                .annotations
2325                .into_iter()
2326                .map(|(k, v)| (k, v.unwrap_or_default()))
2327                .collect(),
2328        }
2329    }
2330}
2331
2332impl TryFrom<cedar_policy::Policy> for Policy {
2333    type Error = cedar_policy::PolicyToJsonError;
2334
2335    fn try_from(value: cedar_policy::Policy) -> Result<Self, Self::Error> {
2336        match value.to_json() {
2337            Ok(json) => Ok(serde_json::from_value(json)?),
2338            Err(e) => Err(e),
2339        }
2340    }
2341}
2342
2343impl TryInto<cedar_policy::Policy> for Policy {
2344    type Error = cedar_policy::PolicyFromJsonError;
2345
2346    fn try_into(self) -> Result<cedar_policy::Policy, Self::Error> {
2347        let json = serde_json::to_value(self).unwrap();
2348        cedar_policy::Policy::from_json(None, json)
2349    }
2350}
2351
2352#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2353#[serde(default)]
2354pub struct Template {
2355    pub effect: PolicyEffect,
2356    pub principal: PrincipalOp,
2357    pub action: ActionOp,
2358    pub resource: ResourceOp,
2359    pub conditions: Vec<Condition>,
2360    #[serde(skip_serializing_if = "HashMap::is_empty")]
2361    pub annotations: HashMap<String, Option<String>>,
2362}
2363
2364impl Template {
2365    pub fn to_cedar(
2366        &self,
2367        policy_id: PolicyId,
2368    ) -> Result<cedar_policy::Template, cedar_policy::PolicyFromJsonError> {
2369        let json = serde_json::to_value(self).unwrap();
2370        cedar_policy::Template::from_json(Some(policy_id.into()), json)
2371    }
2372}
2373
2374impl From<proto::Template> for Template {
2375    fn from(value: proto::Template) -> Self {
2376        Self {
2377            effect: value.effect().into(),
2378            principal: value.principal.unwrap().into(),
2379            action: value.action.unwrap().into(),
2380            resource: value.resource.unwrap().into(),
2381            conditions: value
2382                .conditions
2383                .into_iter()
2384                .map(|c| c.into())
2385                .collect::<Vec<Condition>>(),
2386            annotations: value
2387                .annotations
2388                .into_iter()
2389                .map(|(k, v)| (k, Some(v)))
2390                .collect(),
2391        }
2392    }
2393}
2394
2395impl From<Template> for proto::Template {
2396    fn from(val: Template) -> Self {
2397        proto::Template {
2398            effect: Into::<proto::Effect>::into(val.effect) as i32,
2399            principal: Some(val.principal.into()),
2400            action: Some(val.action.into()),
2401            resource: Some(val.resource.into()),
2402            conditions: val.conditions.into_iter().map(|c| c.into()).collect(),
2403            annotations: val
2404                .annotations
2405                .into_iter()
2406                .map(|(k, v)| (k, v.unwrap_or_default()))
2407                .collect(),
2408        }
2409    }
2410}
2411
2412impl TryFrom<cedar_policy::Template> for Template {
2413    type Error = cedar_policy::PolicyToJsonError;
2414
2415    fn try_from(value: cedar_policy::Template) -> Result<Self, Self::Error> {
2416        match value.to_json() {
2417            Ok(json) => Ok(serde_json::from_value(json).unwrap()),
2418            Err(e) => Err(e),
2419        }
2420    }
2421}
2422
2423impl TryInto<cedar_policy::Template> for Template {
2424    type Error = cedar_policy::PolicyFromJsonError;
2425
2426    fn try_into(self) -> Result<cedar_policy::Template, Self::Error> {
2427        let json = serde_json::to_value(self).unwrap();
2428        cedar_policy::Template::from_json(None, json)
2429    }
2430}
2431
2432#[derive(
2433    Debug, Default, Clone, Eq, PartialOrd, Ord, Hash, PartialEq, Serialize, Deserialize, ToSchema,
2434)]
2435pub struct PolicyId(String);
2436
2437impl From<String> for PolicyId {
2438    fn from(value: String) -> Self {
2439        Self(value)
2440    }
2441}
2442
2443impl From<cedar_policy::PolicyId> for PolicyId {
2444    fn from(value: cedar_policy::PolicyId) -> Self {
2445        Self(value.to_string())
2446    }
2447}
2448
2449impl From<PolicyId> for cedar_policy::PolicyId {
2450    fn from(val: PolicyId) -> Self {
2451        cedar_policy::PolicyId::new(&val.0)
2452    }
2453}
2454
2455impl std::fmt::Display for PolicyId {
2456    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2457        write!(f, "{}", self.0)
2458    }
2459}
2460
2461impl Borrow<str> for PolicyId {
2462    fn borrow(&self) -> &str {
2463        &self.0
2464    }
2465}
2466
2467#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2468#[serde(untagged)]
2469pub enum EntityValue {
2470    EntityUid(EntityUid),
2471    EntityEscape(EntityUidEscape),
2472}
2473
2474impl Default for EntityValue {
2475    fn default() -> Self {
2476        Self::EntityEscape(EntityUidEscape::default())
2477    }
2478}
2479
2480impl From<cedar_policy::EntityUid> for EntityValue {
2481    fn from(value: cedar_policy::EntityUid) -> Self {
2482        Self::EntityEscape(EntityUidEscape::from(value))
2483    }
2484}
2485
2486impl From<EntityValue> for cedar_policy::EntityUid {
2487    fn from(val: EntityValue) -> Self {
2488        match val {
2489            EntityValue::EntityUid(e) => e.into(),
2490            EntityValue::EntityEscape(e) => e.into(),
2491        }
2492    }
2493}
2494
2495impl From<proto::EntityValue> for EntityValue {
2496    fn from(value: proto::EntityValue) -> Self {
2497        match value.value.unwrap() {
2498            proto::entity_value::Value::Ee(e) => EntityValue::EntityEscape(e.into()),
2499            proto::entity_value::Value::Euid(e) => EntityValue::EntityUid(e.into()),
2500        }
2501    }
2502}
2503
2504impl From<EntityValue> for proto::EntityValue {
2505    fn from(val: EntityValue) -> Self {
2506        match val {
2507            EntityValue::EntityUid(e) => proto::EntityValue {
2508                value: Some(proto::entity_value::Value::Euid(e.into())),
2509            },
2510            EntityValue::EntityEscape(e) => proto::EntityValue {
2511                value: Some(proto::entity_value::Value::Ee(e.into())),
2512            },
2513        }
2514    }
2515}
2516
2517#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2518#[serde(rename_all = "camelCase", default)]
2519pub struct TemplateLink {
2520    pub template_id: PolicyId,
2521    pub new_id: PolicyId,
2522    pub values: HashMap<SlotId, EntityValue>,
2523}
2524
2525impl TemplateLink {
2526    pub fn new(
2527        template_id: PolicyId,
2528        new_id: PolicyId,
2529        values: HashMap<SlotId, EntityValue>,
2530    ) -> Self {
2531        Self {
2532            template_id,
2533            new_id,
2534            values,
2535        }
2536    }
2537
2538    pub fn to_cedar_vals(&self) -> HashMap<cedar_policy::SlotId, cedar_policy::EntityUid> {
2539        self.values
2540            .iter()
2541            .map(|(k, v)| (k.clone().into(), v.clone().into()))
2542            .collect()
2543    }
2544}
2545
2546impl From<proto::TemplateLink> for TemplateLink {
2547    fn from(value: proto::TemplateLink) -> Self {
2548        Self {
2549            template_id: value.template_id.into(),
2550            new_id: value.new_id.into(),
2551            values: value
2552                .values
2553                .into_iter()
2554                .map(|(k, v)| (k.into(), v.into()))
2555                .collect(),
2556        }
2557    }
2558}
2559
2560impl From<TemplateLink> for proto::TemplateLink {
2561    fn from(val: TemplateLink) -> Self {
2562        proto::TemplateLink {
2563            template_id: val.template_id.to_string(),
2564            new_id: val.new_id.to_string(),
2565            values: val
2566                .values
2567                .into_iter()
2568                .map(|(k, v)| (k.to_string(), v.into()))
2569                .collect(),
2570        }
2571    }
2572}
2573
2574impl From<cedar_policy::Policy> for TemplateLink {
2575    fn from(value: cedar_policy::Policy) -> Self {
2576        let template_id = value.template_id().unwrap().clone().into();
2577        let new_id = value.id().clone().into();
2578        let template_links = value.template_links().unwrap();
2579
2580        let values = template_links
2581            .into_iter()
2582            .map(|(k, v)| (k.into(), v.into()))
2583            .collect::<HashMap<SlotId, EntityValue>>();
2584
2585        Self {
2586            template_id,
2587            new_id,
2588            values,
2589        }
2590    }
2591}
2592
2593#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2594#[serde(rename_all = "camelCase", default)]
2595pub struct PolicySet {
2596    pub static_policies: HashMap<PolicyId, Policy>,
2597    pub templates: HashMap<PolicyId, Template>,
2598    pub template_links: Vec<TemplateLink>,
2599}
2600
2601impl From<proto::PolicySet> for PolicySet {
2602    fn from(value: proto::PolicySet) -> Self {
2603        Self {
2604            static_policies: value
2605                .static_policies
2606                .into_iter()
2607                .map(|(k, v)| (k.into(), v.into()))
2608                .collect(),
2609            templates: value
2610                .templates
2611                .into_iter()
2612                .map(|(k, v)| (k.into(), v.into()))
2613                .collect(),
2614            template_links: value.template_links.into_iter().map(|v| v.into()).collect(),
2615        }
2616    }
2617}
2618
2619impl From<PolicySet> for proto::PolicySet {
2620    fn from(val: PolicySet) -> Self {
2621        proto::PolicySet {
2622            static_policies: val
2623                .static_policies
2624                .into_iter()
2625                .map(|(k, v)| (k.to_string(), v.into()))
2626                .collect(),
2627            templates: val
2628                .templates
2629                .into_iter()
2630                .map(|(k, v)| (k.to_string(), v.into()))
2631                .collect(),
2632            template_links: val.template_links.into_iter().map(|v| v.into()).collect(),
2633        }
2634    }
2635}
2636
2637impl TryFrom<cedar_policy::PolicySet> for PolicySet {
2638    type Error = cedar_policy::PolicySetError;
2639    fn try_from(value: cedar_policy::PolicySet) -> Result<Self, Self::Error> {
2640        Ok(serde_json::from_value(value.to_json()?).unwrap())
2641    }
2642}
2643
2644impl TryInto<cedar_policy::PolicySet> for PolicySet {
2645    type Error = cedar_policy::PolicySetError;
2646    fn try_into(self) -> Result<cedar_policy::PolicySet, Self::Error> {
2647        cedar_policy::PolicySet::from_json_value(serde_json::to_value(self).unwrap())
2648    }
2649}
2650
2651#[derive(Debug, Clone, Serialize, Deserialize)]
2652pub struct Entities(pub Vec<Entity>);
2653
2654impl From<proto::Entities> for Entities {
2655    fn from(value: proto::Entities) -> Self {
2656        Self(value.entities.into_iter().map(|e| e.into()).collect())
2657    }
2658}
2659
2660impl From<Entities> for proto::Entities {
2661    fn from(val: Entities) -> Self {
2662        proto::Entities {
2663            entities: val.0.into_iter().map(|e| e.into()).collect(),
2664        }
2665    }
2666}
2667
2668impl From<Vec<Entity>> for Entities {
2669    fn from(value: Vec<Entity>) -> Self {
2670        Self(value)
2671    }
2672}
2673
2674impl From<Entities> for Vec<Entity> {
2675    fn from(val: Entities) -> Self {
2676        val.0
2677    }
2678}
2679
2680#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2681pub struct Context(HashMap<String, entity::EntityAttr>);
2682
2683impl Context {
2684    pub fn to_cedar_context(
2685        &self,
2686        schema: Option<(&cedar_policy::Schema, &cedar_policy::EntityUid)>,
2687    ) -> Result<cedar_policy::Context, cedar_policy::ContextJsonError> {
2688        let json = serde_json::to_value(self).unwrap();
2689        cedar_policy::Context::from_json_value(json, schema)
2690    }
2691}
2692
2693#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2694pub enum Decision {
2695    Allow,
2696    #[default]
2697    Deny,
2698}
2699
2700impl From<cedar_policy::Decision> for Decision {
2701    fn from(value: cedar_policy::Decision) -> Self {
2702        match value {
2703            cedar_policy::Decision::Allow => Self::Allow,
2704            cedar_policy::Decision::Deny => Self::Deny,
2705        }
2706    }
2707}
2708
2709#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2710#[serde(default)]
2711pub struct Response {
2712    pub decision: Decision,
2713    pub reason: Vec<String>,
2714    pub errors: Vec<String>,
2715}
2716
2717#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2718pub struct Request {
2719    pub principal: EntityUid,
2720    pub action: EntityUid,
2721    pub resource: EntityUid,
2722    #[serde(skip_serializing_if = "Option::is_none")]
2723    pub context: Option<Context>,
2724}
2725
2726impl From<cedar_policy::Response> for Response {
2727    fn from(value: cedar_policy::Response) -> Self {
2728        let decision = match value.decision() {
2729            cedar_policy::Decision::Allow => Decision::Allow,
2730            cedar_policy::Decision::Deny => Decision::Deny,
2731        };
2732        let reason = value
2733            .diagnostics()
2734            .reason()
2735            .map(|r| r.to_string())
2736            .collect::<Vec<String>>();
2737        let errors = value
2738            .diagnostics()
2739            .errors()
2740            .map(|e| e.to_string())
2741            .collect::<Vec<String>>();
2742
2743        Self {
2744            decision,
2745            reason,
2746            errors,
2747        }
2748    }
2749}
2750
2751#[cfg(test)]
2752mod tests {
2753    // TODO: Create tests
2754}