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 #[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 #[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 }