1use super::{
18 JsonDeserializationError, JsonDeserializationErrorContext, JsonSerializationError, SchemaType,
19};
20use crate::ast::{
21 expression_construction_errors, BorrowedRestrictedExpr, Eid, EntityUID, ExprConstructionError,
22 ExprKind, Literal, Name, RestrictedExpr, Unknown, Value, ValueKind,
23};
24use crate::entities::{
25 schematype_of_restricted_expr, EntitySchemaConformanceError, EscapeKind, GetSchemaTypeError,
26 TypeMismatchError,
27};
28use crate::extensions::Extensions;
29use crate::FromNormalizedStr;
30use either::Either;
31use serde::{Deserialize, Serialize};
32use serde_with::serde_as;
33use serde_with::{DeserializeAs, SerializeAs};
34use smol_str::SmolStr;
35use std::collections::{BTreeMap, HashSet};
36use std::sync::Arc;
37
38#[cfg(feature = "wasm")]
39extern crate tsify;
40
41#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
50#[serde(untagged)]
51#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
52#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
53pub enum CedarValueJson {
54 ExprEscape {
56 #[cfg_attr(feature = "wasm", tsify(type = "string"))]
58 __expr: SmolStr,
59 },
60 EntityEscape {
69 __entity: TypeAndId,
71 },
72 ExtnEscape {
81 __extn: FnAndArg,
83 },
84 Bool(bool),
86 Long(i64),
88 String(#[cfg_attr(feature = "wasm", tsify(type = "string"))] SmolStr),
90 Set(Vec<CedarValueJson>),
93 Record(
96 #[cfg_attr(feature = "wasm", tsify(type = "{ [key: string]: CedarValueJson }"))] JsonRecord,
97 ),
98 Null,
101}
102
103#[serde_as]
105#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
106pub struct JsonRecord {
107 #[serde_as(as = "serde_with::MapPreventDuplicates<_, _>")]
110 #[serde(flatten)]
111 values: BTreeMap<SmolStr, CedarValueJson>,
112}
113
114impl IntoIterator for JsonRecord {
115 type Item = (SmolStr, CedarValueJson);
116 type IntoIter = <BTreeMap<SmolStr, CedarValueJson> as IntoIterator>::IntoIter;
117 fn into_iter(self) -> Self::IntoIter {
118 self.values.into_iter()
119 }
120}
121
122impl<'a> IntoIterator for &'a JsonRecord {
123 type Item = (&'a SmolStr, &'a CedarValueJson);
124 type IntoIter = <&'a BTreeMap<SmolStr, CedarValueJson> as IntoIterator>::IntoIter;
125 fn into_iter(self) -> Self::IntoIter {
126 self.values.iter()
127 }
128}
129
130impl FromIterator<(SmolStr, CedarValueJson)> for JsonRecord {
137 fn from_iter<T: IntoIterator<Item = (SmolStr, CedarValueJson)>>(iter: T) -> Self {
138 Self {
139 values: BTreeMap::from_iter(iter),
140 }
141 }
142}
143
144impl JsonRecord {
145 pub fn iter(&self) -> impl Iterator<Item = (&'_ SmolStr, &'_ CedarValueJson)> {
147 self.values.iter()
148 }
149
150 pub fn len(&self) -> usize {
152 self.values.len()
153 }
154
155 pub fn is_empty(&self) -> bool {
157 self.values.is_empty()
158 }
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
163#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
164#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
165pub struct TypeAndId {
166 #[cfg_attr(feature = "wasm", tsify(type = "string"))]
168 #[serde(rename = "type")]
169 entity_type: SmolStr,
170 #[cfg_attr(feature = "wasm", tsify(type = "string"))]
172 id: SmolStr,
173}
174
175impl From<EntityUID> for TypeAndId {
176 fn from(euid: EntityUID) -> TypeAndId {
177 let (entity_type, eid) = euid.components();
178 TypeAndId {
179 entity_type: entity_type.to_string().into(),
180 id: AsRef::<str>::as_ref(&eid).into(),
181 }
182 }
183}
184
185impl From<&EntityUID> for TypeAndId {
186 fn from(euid: &EntityUID) -> TypeAndId {
187 TypeAndId {
188 entity_type: euid.entity_type().to_string().into(),
189 id: AsRef::<str>::as_ref(&euid.eid()).into(),
190 }
191 }
192}
193
194impl TryFrom<TypeAndId> for EntityUID {
195 type Error = crate::parser::err::ParseErrors;
196
197 fn try_from(e: TypeAndId) -> Result<EntityUID, Self::Error> {
198 Ok(EntityUID::from_components(
199 Name::from_normalized_str(&e.entity_type)?,
200 Eid::new(e.id),
201 None,
202 ))
203 }
204}
205
206#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
208#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
209#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
210pub struct FnAndArg {
211 #[serde(rename = "fn")]
213 #[cfg_attr(feature = "wasm", tsify(type = "string"))]
214 pub(crate) ext_fn: SmolStr,
215 pub(crate) arg: Box<CedarValueJson>,
217}
218
219impl CedarValueJson {
220 pub fn uid(euid: &EntityUID) -> Self {
222 Self::EntityEscape {
223 __entity: TypeAndId::from(euid.clone()),
224 }
225 }
226
227 pub fn into_expr(
229 self,
230 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
231 ) -> Result<RestrictedExpr, JsonDeserializationError> {
232 match self {
233 Self::Bool(b) => Ok(RestrictedExpr::val(b)),
234 Self::Long(i) => Ok(RestrictedExpr::val(i)),
235 Self::String(s) => Ok(RestrictedExpr::val(s)),
236 Self::Set(vals) => Ok(RestrictedExpr::set(
237 vals.into_iter()
238 .map(|v| v.into_expr(ctx.clone()))
239 .collect::<Result<Vec<_>, _>>()?,
240 )),
241 Self::Record(map) => Ok(RestrictedExpr::record(
242 map.into_iter()
243 .map(|(k, v)| Ok((k, v.into_expr(ctx.clone())?)))
244 .collect::<Result<Vec<_>, JsonDeserializationError>>()?,
245 )
246 .map_err(|e| match e {
247 ExprConstructionError::DuplicateKey(
248 expression_construction_errors::DuplicateKeyError { key, .. },
249 ) => JsonDeserializationError::duplicate_key(ctx(), key),
250 })?),
251 Self::EntityEscape { __entity: entity } => Ok(RestrictedExpr::val(
252 EntityUID::try_from(entity.clone()).map_err(|errs| {
253 JsonDeserializationError::ParseEscape {
254 kind: EscapeKind::Entity,
255 value: serde_json::to_string_pretty(&entity)
256 .unwrap_or_else(|_| format!("{:?}", &entity)),
257 errs,
258 }
259 })?,
260 )),
261 Self::ExtnEscape { __extn: extn } => extn.into_expr(ctx),
262 Self::ExprEscape { .. } => Err(JsonDeserializationError::ExprTag(Box::new(ctx()))),
263 Self::Null => Err(JsonDeserializationError::Null(Box::new(ctx()))),
264 }
265 }
266
267 pub fn from_expr(expr: BorrowedRestrictedExpr<'_>) -> Result<Self, JsonSerializationError> {
269 match expr.as_ref().expr_kind() {
270 ExprKind::Lit(lit) => Ok(Self::from_lit(lit.clone())),
271 ExprKind::ExtensionFunctionApp { fn_name, args } => match args.len() {
272 0 => Err(JsonSerializationError::ExtnCall0Arguments {
273 func: fn_name.clone(),
274 }),
275 #[allow(clippy::indexing_slicing)]
277 1 => Ok(Self::ExtnEscape {
278 __extn: FnAndArg {
279 ext_fn: fn_name.to_string().into(),
280 arg: Box::new(CedarValueJson::from_expr(
281 BorrowedRestrictedExpr::new_unchecked(
283 &args[0], ),
285 )?),
286 },
287 }),
288 _ => Err(JsonSerializationError::ExtnCall2OrMoreArguments {
289 func: fn_name.clone(),
290 }),
291 },
292 ExprKind::Set(exprs) => Ok(Self::Set(
293 exprs
294 .iter()
295 .map(BorrowedRestrictedExpr::new_unchecked) .map(CedarValueJson::from_expr)
297 .collect::<Result<_, JsonSerializationError>>()?,
298 )),
299 ExprKind::Record(map) => {
300 check_for_reserved_keys(map.keys())?;
304 Ok(Self::Record(
305 map.iter()
306 .map(|(k, v)| {
307 Ok((
308 k.clone(),
309 CedarValueJson::from_expr(
310 BorrowedRestrictedExpr::new_unchecked(v),
312 )?,
313 ))
314 })
315 .collect::<Result<_, JsonSerializationError>>()?,
316 ))
317 }
318 kind => {
319 Err(JsonSerializationError::UnexpectedRestrictedExprKind { kind: kind.clone() })
320 }
321 }
322 }
323
324 pub fn from_value(value: Value) -> Result<Self, JsonSerializationError> {
335 Self::from_valuekind(value.value)
336 }
337
338 pub fn from_valuekind(value: ValueKind) -> Result<Self, JsonSerializationError> {
342 match value {
343 ValueKind::Lit(lit) => Ok(Self::from_lit(lit)),
344 ValueKind::Set(set) => Ok(Self::Set(
345 set.iter()
346 .cloned()
347 .map(Self::from_value)
348 .collect::<Result<_, _>>()?,
349 )),
350 ValueKind::Record(record) => {
351 check_for_reserved_keys(record.keys())?;
355 Ok(Self::Record(
356 record
357 .iter()
358 .map(|(k, v)| Ok((k.clone(), Self::from_value(v.clone())?)))
359 .collect::<Result<JsonRecord, JsonSerializationError>>()?,
360 ))
361 }
362 ValueKind::ExtensionValue(ev) => {
363 let ext_fn: &Name = &ev.constructor;
364 Ok(Self::ExtnEscape {
365 __extn: FnAndArg {
366 ext_fn: ext_fn.to_string().into(),
367 arg: match ev.args.as_slice() {
368 [ref expr] => Box::new(Self::from_expr(expr.as_borrowed())?),
369 [] => {
370 return Err(JsonSerializationError::ExtnCall0Arguments {
371 func: ext_fn.clone(),
372 })
373 }
374 _ => {
375 return Err(JsonSerializationError::ExtnCall2OrMoreArguments {
376 func: ext_fn.clone(),
377 })
378 }
379 },
380 },
381 })
382 }
383 }
384 }
385
386 pub fn from_lit(lit: Literal) -> Self {
388 match lit {
389 Literal::Bool(b) => Self::Bool(b),
390 Literal::Long(i) => Self::Long(i),
391 Literal::String(s) => Self::String(s),
392 Literal::EntityUID(euid) => Self::EntityEscape {
393 __entity: Arc::unwrap_or_clone(euid).into(),
394 },
395 }
396 }
397}
398
399fn check_for_reserved_keys<'a>(
402 mut keys: impl Iterator<Item = &'a SmolStr>,
403) -> Result<(), JsonSerializationError> {
404 let reserved_keys: HashSet<&str> = HashSet::from_iter(["__entity", "__extn", "__expr"]);
409 let collision = keys.find(|k| reserved_keys.contains(k.as_str()));
410 match collision {
411 Some(collision) => Err(JsonSerializationError::ReservedKey {
412 key: collision.clone(),
413 }),
414 None => Ok(()),
415 }
416}
417
418impl FnAndArg {
419 pub fn into_expr(
421 self,
422 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
423 ) -> Result<RestrictedExpr, JsonDeserializationError> {
424 Ok(RestrictedExpr::call_extension_fn(
425 Name::from_normalized_str(&self.ext_fn).map_err(|errs| {
426 JsonDeserializationError::ParseEscape {
427 kind: EscapeKind::Extension,
428 value: self.ext_fn.to_string(),
429 errs,
430 }
431 })?,
432 vec![CedarValueJson::into_expr(*self.arg, ctx)?],
433 ))
434 }
435}
436
437#[derive(Debug, Clone)]
439pub struct ValueParser<'e> {
440 extensions: Extensions<'e>,
442}
443
444impl<'e> ValueParser<'e> {
445 pub fn new(extensions: Extensions<'e>) -> Self {
447 Self { extensions }
448 }
449
450 pub fn val_into_restricted_expr(
455 &self,
456 val: serde_json::Value,
457 expected_ty: Option<&SchemaType>,
458 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
459 ) -> Result<RestrictedExpr, JsonDeserializationError> {
460 let parse_as_unknown = |val: serde_json::Value| {
463 let extjson: ExtnValueJson = serde_json::from_value(val).ok()?;
464 match extjson {
465 ExtnValueJson::ExplicitExtnEscape {
466 __extn: FnAndArg { ext_fn, arg },
467 } if ext_fn == "unknown" => {
468 let arg = arg.into_expr(ctx.clone()).ok()?;
469 let name = arg.as_string()?;
470 Some(RestrictedExpr::unknown(Unknown::new_untyped(name.clone())))
471 }
472 _ => None, }
474 };
475 if let Some(rexpr) = parse_as_unknown(val.clone()) {
476 return Ok(rexpr);
477 }
478 match expected_ty {
480 Some(SchemaType::Entity { .. }) => {
485 let uidjson: EntityUidJson = serde_json::from_value(val)?;
486 Ok(RestrictedExpr::val(uidjson.into_euid(ctx)?))
487 }
488 Some(SchemaType::Extension { ref name, .. }) => {
493 let extjson: ExtnValueJson = serde_json::from_value(val)?;
494 self.extn_value_json_into_rexpr(extjson, name.clone(), ctx)
495 }
496 Some(expected_ty @ SchemaType::Set { element_ty }) => match val {
499 serde_json::Value::Array(elements) => Ok(RestrictedExpr::set(
500 elements
501 .into_iter()
502 .map(|element| {
503 self.val_into_restricted_expr(element, Some(element_ty), ctx.clone())
504 })
505 .collect::<Result<Vec<RestrictedExpr>, JsonDeserializationError>>()?,
506 )),
507 val => {
508 let actual_val = {
509 let jvalue: CedarValueJson = serde_json::from_value(val)?;
510 jvalue.into_expr(ctx.clone())?
511 };
512 let err = TypeMismatchError {
513 expected: Box::new(expected_ty.clone()),
514 actual_ty: match schematype_of_restricted_expr(
515 actual_val.as_borrowed(),
516 self.extensions,
517 ) {
518 Ok(actual_ty) => Some(Box::new(actual_ty)),
519 Err(_) => None, },
521 actual_val: Either::Right(Box::new(actual_val)),
522 };
523 match ctx() {
524 JsonDeserializationErrorContext::EntityAttribute { uid, attr } => {
525 Err(JsonDeserializationError::EntitySchemaConformance(
526 EntitySchemaConformanceError::TypeMismatch { uid, attr, err },
527 ))
528 }
529 ctx => Err(JsonDeserializationError::TypeMismatch {
530 ctx: Box::new(ctx),
531 err,
532 }),
533 }
534 }
535 },
536 Some(
540 expected_ty @ SchemaType::Record {
541 attrs: expected_attrs,
542 open_attrs,
543 },
544 ) => match val {
545 serde_json::Value::Object(mut actual_attrs) => {
546 let ctx2 = ctx.clone(); let mut_actual_attrs = &mut actual_attrs; let rexpr_pairs = expected_attrs
549 .iter()
550 .filter_map(move |(k, expected_attr_ty)| {
551 match mut_actual_attrs.remove(k.as_str()) {
552 Some(actual_attr) => {
553 match self.val_into_restricted_expr(actual_attr, Some(expected_attr_ty.schema_type()), ctx.clone()) {
554 Ok(actual_attr) => Some(Ok((k.clone(), actual_attr))),
555 Err(e) => Some(Err(e)),
556 }
557 }
558 None if expected_attr_ty.is_required() => Some(Err(JsonDeserializationError::MissingRequiredRecordAttr {
559 ctx: Box::new(ctx()),
560 record_attr: k.clone(),
561 })),
562 None => None,
563 }
564 })
565 .collect::<Result<Vec<(SmolStr, RestrictedExpr)>, JsonDeserializationError>>()?;
566
567 if !open_attrs {
568 if let Some((record_attr, _)) = actual_attrs.into_iter().next() {
571 return Err(JsonDeserializationError::UnexpectedRecordAttr {
572 ctx: Box::new(ctx2()),
573 record_attr: record_attr.into(),
574 });
575 }
576 }
577
578 RestrictedExpr::record(rexpr_pairs).map_err(|e| match e {
583 ExprConstructionError::DuplicateKey(
584 expression_construction_errors::DuplicateKeyError { key, .. },
585 ) => JsonDeserializationError::duplicate_key(ctx2(), key),
586 })
587 }
588 val => {
589 let actual_val = {
590 let jvalue: CedarValueJson = serde_json::from_value(val)?;
591 jvalue.into_expr(ctx.clone())?
592 };
593 let err = TypeMismatchError {
594 expected: Box::new(expected_ty.clone()),
595 actual_ty: match schematype_of_restricted_expr(
596 actual_val.as_borrowed(),
597 self.extensions,
598 ) {
599 Ok(actual_ty) => Some(Box::new(actual_ty)),
600 Err(_) => None, },
602 actual_val: Either::Right(Box::new(actual_val)),
603 };
604 match ctx() {
605 JsonDeserializationErrorContext::EntityAttribute { uid, attr } => {
606 Err(JsonDeserializationError::EntitySchemaConformance(
607 EntitySchemaConformanceError::TypeMismatch { uid, attr, err },
608 ))
609 }
610 ctx => Err(JsonDeserializationError::TypeMismatch {
611 ctx: Box::new(ctx),
612 err,
613 }),
614 }
615 }
616 },
617 Some(_) | None => {
620 let jvalue: CedarValueJson = serde_json::from_value(val)?;
623 Ok(jvalue.into_expr(ctx)?)
624 }
625 }
626 }
627
628 fn extn_value_json_into_rexpr(
633 &self,
634 extnjson: ExtnValueJson,
635 expected_typename: Name,
636 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
637 ) -> Result<RestrictedExpr, JsonDeserializationError> {
638 match extnjson {
639 ExtnValueJson::ExplicitExprEscape { __expr } => {
640 Err(JsonDeserializationError::ExprTag(Box::new(ctx())))
641 }
642 ExtnValueJson::ExplicitExtnEscape { __extn }
643 | ExtnValueJson::ImplicitExtnEscape(__extn) => {
644 let jvalue = CedarValueJson::ExtnEscape { __extn };
646 let expr = jvalue.into_expr(ctx.clone())?;
647 match expr.expr_kind() {
648 ExprKind::ExtensionFunctionApp { .. } => Ok(expr),
649 _ => Err(JsonDeserializationError::ExpectedExtnValue {
650 ctx: Box::new(ctx()),
651 got: Box::new(Either::Right(expr.clone().into())),
652 }),
653 }
654 }
655 ExtnValueJson::ImplicitConstructor(val) => {
656 let arg = val.into_expr(ctx.clone())?;
657 let argty = schematype_of_restricted_expr(arg.as_borrowed(), self.extensions)
658 .map_err(|e| match e {
659 GetSchemaTypeError::HeterogeneousSet(err) => match ctx() {
660 JsonDeserializationErrorContext::EntityAttribute { uid, attr } => {
661 JsonDeserializationError::EntitySchemaConformance(
662 EntitySchemaConformanceError::HeterogeneousSet {
663 uid,
664 attr,
665 err,
666 },
667 )
668 }
669 ctx => JsonDeserializationError::HeterogeneousSet {
670 ctx: Box::new(ctx),
671 err,
672 },
673 },
674 GetSchemaTypeError::ExtensionFunctionLookup(err) => match ctx() {
675 JsonDeserializationErrorContext::EntityAttribute { uid, attr } => {
676 JsonDeserializationError::EntitySchemaConformance(
677 EntitySchemaConformanceError::ExtensionFunctionLookup {
678 uid,
679 attr,
680 err,
681 },
682 )
683 }
684 ctx => JsonDeserializationError::ExtensionFunctionLookup {
685 ctx: Box::new(ctx),
686 err,
687 },
688 },
689 GetSchemaTypeError::UnknownInsufficientTypeInfo { .. }
690 | GetSchemaTypeError::NontrivialResidual { .. } => {
691 JsonDeserializationError::UnknownInImplicitConstructorArg {
692 ctx: Box::new(ctx()),
693 arg: Box::new(arg.clone()),
694 }
695 }
696 })?;
697 let func = self
698 .extensions
699 .lookup_single_arg_constructor(
700 &SchemaType::Extension {
701 name: expected_typename.clone(),
702 },
703 &argty,
704 )
705 .map_err(|err| JsonDeserializationError::ExtensionFunctionLookup {
706 ctx: Box::new(ctx()),
707 err,
708 })?
709 .ok_or_else(|| JsonDeserializationError::MissingImpliedConstructor {
710 ctx: Box::new(ctx()),
711 return_type: Box::new(SchemaType::Extension {
712 name: expected_typename,
713 }),
714 arg_type: Box::new(argty.clone()),
715 })?;
716 Ok(RestrictedExpr::call_extension_fn(
717 func.name().clone(),
718 vec![arg],
719 ))
720 }
721 }
722 }
723}
724
725pub trait DeserializationContext {
729 fn static_context() -> Option<JsonDeserializationErrorContext>;
732}
733
734#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
737pub struct NoStaticContext;
738
739impl DeserializationContext for NoStaticContext {
740 fn static_context() -> Option<JsonDeserializationErrorContext> {
741 None
742 }
743}
744
745#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
748#[serde(untagged)]
749#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
750#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
751pub enum EntityUidJson<Context = NoStaticContext> {
752 ExplicitExprEscape {
754 __expr: String,
756 #[serde(skip)]
758 context: std::marker::PhantomData<Context>,
759 },
760 ExplicitEntityEscape {
762 __entity: TypeAndId,
764 },
765 ImplicitEntityEscape(TypeAndId),
768
769 FoundValue(#[cfg_attr(feature = "wasm", tsify(type = "__skip"))] serde_json::Value),
771}
772
773impl<'de, C: DeserializationContext> DeserializeAs<'de, EntityUID> for EntityUidJson<C> {
774 fn deserialize_as<D>(deserializer: D) -> Result<EntityUID, D::Error>
775 where
776 D: serde::Deserializer<'de>,
777 {
778 use serde::de::Error;
779 let context = || JsonDeserializationErrorContext::Unknown;
781 let s = EntityUidJson::<C>::deserialize(deserializer)?;
782 let euid = s.into_euid(context).map_err(Error::custom)?;
783 Ok(euid)
784 }
785}
786
787impl<C> SerializeAs<EntityUID> for EntityUidJson<C> {
788 fn serialize_as<S>(source: &EntityUID, serializer: S) -> Result<S::Ok, S::Error>
789 where
790 S: serde::Serializer,
791 {
792 let json: EntityUidJson = source.clone().into();
793 json.serialize(serializer)
794 }
795}
796
797impl<C: DeserializationContext> EntityUidJson<C> {
798 pub fn new(entity_type: impl Into<SmolStr>, id: impl Into<SmolStr>) -> Self {
802 Self::ImplicitEntityEscape(TypeAndId {
803 entity_type: entity_type.into(),
804 id: id.into(),
805 })
806 }
807
808 pub fn into_euid(
810 self,
811 dynamic_ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
812 ) -> Result<EntityUID, JsonDeserializationError> {
813 let ctx = || C::static_context().unwrap_or_else(&dynamic_ctx);
814 match self {
815 Self::ExplicitEntityEscape { __entity } | Self::ImplicitEntityEscape(__entity) => {
816 let jvalue = CedarValueJson::EntityEscape { __entity };
818 let expr = jvalue.into_expr(&ctx)?;
819 match expr.expr_kind() {
820 ExprKind::Lit(Literal::EntityUID(euid)) => Ok((**euid).clone()),
821 _ => Err(JsonDeserializationError::ExpectedLiteralEntityRef {
822 ctx: Box::new(ctx()),
823 got: Box::new(Either::Right(expr.clone().into())),
824 }),
825 }
826 }
827 Self::FoundValue(v) => Err(JsonDeserializationError::ExpectedLiteralEntityRef {
828 ctx: Box::new(ctx()),
829 got: Box::new(Either::Left(v)),
830 }),
831 Self::ExplicitExprEscape { __expr, .. } => {
832 Err(JsonDeserializationError::ExprTag(Box::new(ctx())))
833 }
834 }
835 }
836}
837
838impl From<EntityUID> for EntityUidJson {
840 fn from(uid: EntityUID) -> EntityUidJson {
841 EntityUidJson::ExplicitEntityEscape {
842 __entity: uid.into(),
843 }
844 }
845}
846
847impl From<&EntityUID> for EntityUidJson {
849 fn from(uid: &EntityUID) -> EntityUidJson {
850 EntityUidJson::ExplicitEntityEscape {
851 __entity: uid.into(),
852 }
853 }
854}
855
856#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
859#[serde(untagged)]
860pub enum ExtnValueJson {
861 ExplicitExprEscape {
863 __expr: String,
865 },
866 ExplicitExtnEscape {
868 __extn: FnAndArg,
870 },
871 ImplicitExtnEscape(FnAndArg),
874 ImplicitConstructor(CedarValueJson),
880}