1use super::{
18 err::{JsonDeserializationError, JsonDeserializationErrorContext, JsonSerializationError},
19 SchemaType,
20};
21use crate::entities::{
22 conformance::err::EntitySchemaConformanceError,
23 json::err::{EscapeKind, TypeMismatchError},
24};
25use crate::extensions::Extensions;
26use crate::FromNormalizedStr;
27use crate::{
28 ast::{
29 expression_construction_errors, BorrowedRestrictedExpr, Eid, EntityUID, ExprKind,
30 ExpressionConstructionError, Literal, RestrictedExpr, Unknown, Value, ValueKind,
31 },
32 entities::Name,
33};
34use either::Either;
35use serde::{Deserialize, Serialize};
36use serde_with::serde_as;
37use serde_with::{DeserializeAs, SerializeAs};
38use smol_str::{SmolStr, ToSmolStr};
39use std::collections::{BTreeMap, HashSet};
40use std::sync::Arc;
41
42#[cfg(feature = "wasm")]
43extern crate tsify;
44
45#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
54#[serde(untagged)]
55#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
56#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
57pub enum CedarValueJson {
58 ExprEscape {
60 #[cfg_attr(feature = "wasm", tsify(type = "__skip"))]
62 __expr: SmolStr,
63 },
64 EntityEscape {
73 __entity: TypeAndId,
75 },
76 ExtnEscape {
85 __extn: FnAndArg,
87 },
88 Bool(bool),
90 Long(i64),
92 String(#[cfg_attr(feature = "wasm", tsify(type = "string"))] SmolStr),
94 Set(Vec<CedarValueJson>),
97 Record(
100 #[cfg_attr(feature = "wasm", tsify(type = "{ [key: string]: CedarValueJson }"))] JsonRecord,
101 ),
102 Null,
105}
106
107#[serde_as]
109#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
110pub struct JsonRecord {
111 #[serde_as(as = "serde_with::MapPreventDuplicates<_, _>")]
114 #[serde(flatten)]
115 values: BTreeMap<SmolStr, CedarValueJson>,
116}
117
118impl IntoIterator for JsonRecord {
119 type Item = (SmolStr, CedarValueJson);
120 type IntoIter = <BTreeMap<SmolStr, CedarValueJson> as IntoIterator>::IntoIter;
121 fn into_iter(self) -> Self::IntoIter {
122 self.values.into_iter()
123 }
124}
125
126impl<'a> IntoIterator for &'a JsonRecord {
127 type Item = (&'a SmolStr, &'a CedarValueJson);
128 type IntoIter = <&'a BTreeMap<SmolStr, CedarValueJson> as IntoIterator>::IntoIter;
129 fn into_iter(self) -> Self::IntoIter {
130 self.values.iter()
131 }
132}
133
134impl FromIterator<(SmolStr, CedarValueJson)> for JsonRecord {
141 fn from_iter<T: IntoIterator<Item = (SmolStr, CedarValueJson)>>(iter: T) -> Self {
142 Self {
143 values: BTreeMap::from_iter(iter),
144 }
145 }
146}
147
148impl JsonRecord {
149 pub fn iter(&self) -> impl Iterator<Item = (&'_ SmolStr, &'_ CedarValueJson)> {
151 self.values.iter()
152 }
153
154 pub fn len(&self) -> usize {
156 self.values.len()
157 }
158
159 pub fn is_empty(&self) -> bool {
161 self.values.is_empty()
162 }
163}
164
165#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
167#[serde(rename_all = "camelCase")]
168#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
169#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
170pub struct TypeAndId {
171 #[cfg_attr(feature = "wasm", tsify(type = "string"))]
173 #[serde(rename = "type")]
174 entity_type: SmolStr,
175 #[cfg_attr(feature = "wasm", tsify(type = "string"))]
177 id: SmolStr,
178}
179
180impl From<EntityUID> for TypeAndId {
181 fn from(euid: EntityUID) -> TypeAndId {
182 let (entity_type, eid) = euid.components();
183 TypeAndId {
184 entity_type: entity_type.to_string().into(),
185 id: AsRef::<str>::as_ref(&eid).into(),
186 }
187 }
188}
189
190impl From<&EntityUID> for TypeAndId {
191 fn from(euid: &EntityUID) -> TypeAndId {
192 TypeAndId {
193 entity_type: euid.entity_type().to_string().into(),
194 id: AsRef::<str>::as_ref(&euid.eid()).into(),
195 }
196 }
197}
198
199impl TryFrom<TypeAndId> for EntityUID {
200 type Error = crate::parser::err::ParseErrors;
201
202 fn try_from(e: TypeAndId) -> Result<EntityUID, Self::Error> {
203 Ok(EntityUID::from_components(
204 Name::from_normalized_str(&e.entity_type)?.into(),
205 Eid::new(e.id),
206 None,
207 ))
208 }
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
213#[serde(rename_all = "camelCase")]
214#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
215#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
216pub struct FnAndArg {
217 #[serde(rename = "fn")]
219 #[cfg_attr(feature = "wasm", tsify(type = "string"))]
220 pub(crate) ext_fn: SmolStr,
221 pub(crate) arg: Box<CedarValueJson>,
223}
224
225impl CedarValueJson {
226 pub fn uid(euid: &EntityUID) -> Self {
228 Self::EntityEscape {
229 __entity: TypeAndId::from(euid.clone()),
230 }
231 }
232
233 pub fn into_expr(
235 self,
236 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
237 ) -> Result<RestrictedExpr, JsonDeserializationError> {
238 match self {
239 Self::Bool(b) => Ok(RestrictedExpr::val(b)),
240 Self::Long(i) => Ok(RestrictedExpr::val(i)),
241 Self::String(s) => Ok(RestrictedExpr::val(s)),
242 Self::Set(vals) => Ok(RestrictedExpr::set(
243 vals.into_iter()
244 .map(|v| v.into_expr(ctx.clone()))
245 .collect::<Result<Vec<_>, _>>()?,
246 )),
247 Self::Record(map) => Ok(RestrictedExpr::record(
248 map.into_iter()
249 .map(|(k, v)| Ok((k, v.into_expr(ctx.clone())?)))
250 .collect::<Result<Vec<_>, JsonDeserializationError>>()?,
251 )
252 .map_err(|e| match e {
253 ExpressionConstructionError::DuplicateKey(
254 expression_construction_errors::DuplicateKeyError { key, .. },
255 ) => JsonDeserializationError::duplicate_key(ctx(), key),
256 })?),
257 Self::EntityEscape { __entity: entity } => Ok(RestrictedExpr::val(
258 EntityUID::try_from(entity.clone()).map_err(|errs| {
259 let err_msg = serde_json::to_string_pretty(&entity)
260 .unwrap_or_else(|_| format!("{:?}", &entity));
261 JsonDeserializationError::parse_escape(EscapeKind::Entity, err_msg, errs)
262 })?,
263 )),
264 Self::ExtnEscape { __extn: extn } => extn.into_expr(ctx),
265 Self::ExprEscape { .. } => Err(JsonDeserializationError::ExprTag(Box::new(ctx()))),
266 Self::Null => Err(JsonDeserializationError::Null(Box::new(ctx()))),
267 }
268 }
269
270 pub fn from_expr(expr: BorrowedRestrictedExpr<'_>) -> Result<Self, JsonSerializationError> {
272 match expr.as_ref().expr_kind() {
273 ExprKind::Lit(lit) => Ok(Self::from_lit(lit.clone())),
274 ExprKind::ExtensionFunctionApp { fn_name, args } => match args.len() {
275 0 => Err(JsonSerializationError::call_0_args(fn_name.clone())),
276 #[allow(clippy::indexing_slicing)]
278 1 => Ok(Self::ExtnEscape {
279 __extn: FnAndArg {
280 ext_fn: fn_name.to_string().into(),
281 arg: Box::new(CedarValueJson::from_expr(
282 BorrowedRestrictedExpr::new_unchecked(
284 &args[0], ),
286 )?),
287 },
288 }),
289 _ => Err(JsonSerializationError::call_2_or_more_args(fn_name.clone())),
290 },
291 ExprKind::Set(exprs) => Ok(Self::Set(
292 exprs
293 .iter()
294 .map(BorrowedRestrictedExpr::new_unchecked) .map(CedarValueJson::from_expr)
296 .collect::<Result<_, JsonSerializationError>>()?,
297 )),
298 ExprKind::Record(map) => {
299 check_for_reserved_keys(map.keys())?;
303 Ok(Self::Record(
304 map.iter()
305 .map(|(k, v)| {
306 Ok((
307 k.clone(),
308 CedarValueJson::from_expr(
309 BorrowedRestrictedExpr::new_unchecked(v),
311 )?,
312 ))
313 })
314 .collect::<Result<_, JsonSerializationError>>()?,
315 ))
316 }
317 kind => Err(JsonSerializationError::unexpected_restricted_expr_kind(
318 kind.clone(),
319 )),
320 }
321 }
322
323 pub fn from_value(value: Value) -> Result<Self, JsonSerializationError> {
334 Self::from_valuekind(value.value)
335 }
336
337 pub fn from_valuekind(value: ValueKind) -> Result<Self, JsonSerializationError> {
341 match value {
342 ValueKind::Lit(lit) => Ok(Self::from_lit(lit)),
343 ValueKind::Set(set) => Ok(Self::Set(
344 set.iter()
345 .cloned()
346 .map(Self::from_value)
347 .collect::<Result<_, _>>()?,
348 )),
349 ValueKind::Record(record) => {
350 check_for_reserved_keys(record.keys())?;
354 Ok(Self::Record(
355 record
356 .iter()
357 .map(|(k, v)| Ok((k.clone(), Self::from_value(v.clone())?)))
358 .collect::<Result<JsonRecord, JsonSerializationError>>()?,
359 ))
360 }
361 ValueKind::ExtensionValue(ev) => {
362 let ext_func = &ev.func;
363 Ok(Self::ExtnEscape {
364 __extn: FnAndArg {
365 ext_fn: ext_func.to_smolstr(),
366 arg: match ev.args.as_slice() {
367 [ref expr] => Box::new(Self::from_expr(expr.as_borrowed())?),
368 [] => {
369 return Err(JsonSerializationError::call_0_args(ext_func.clone()))
370 }
371 _ => {
372 return Err(JsonSerializationError::call_2_or_more_args(
373 ext_func.clone(),
374 ))
375 }
376 },
377 },
378 })
379 }
380 }
381 }
382
383 pub fn from_lit(lit: Literal) -> Self {
385 match lit {
386 Literal::Bool(b) => Self::Bool(b),
387 Literal::Long(i) => Self::Long(i),
388 Literal::String(s) => Self::String(s),
389 Literal::EntityUID(euid) => Self::EntityEscape {
390 __entity: Arc::unwrap_or_clone(euid).into(),
391 },
392 }
393 }
394
395 pub fn sub_entity_literals(
397 self,
398 mapping: &BTreeMap<EntityUID, EntityUID>,
399 ) -> Result<Self, JsonDeserializationError> {
400 match self.clone() {
401 CedarValueJson::ExprEscape { __expr } => Err(JsonDeserializationError::ExprTag(
403 Box::new(JsonDeserializationErrorContext::Unknown),
404 )),
405 CedarValueJson::EntityEscape { __entity } => {
406 let euid = EntityUID::try_from(__entity);
407 match euid {
408 Ok(euid) => match mapping.get(&euid) {
409 Some(new_euid) => Ok(CedarValueJson::EntityEscape {
410 __entity: new_euid.into(),
411 }),
412 None => Ok(self),
413 },
414 Err(_) => Ok(self),
415 }
416 }
417 CedarValueJson::ExtnEscape { __extn } => Ok(CedarValueJson::ExtnEscape {
418 __extn: FnAndArg {
419 ext_fn: __extn.ext_fn,
420 arg: Box::new((*__extn.arg).sub_entity_literals(mapping)?),
421 },
422 }),
423 CedarValueJson::Bool(_) => Ok(self),
424 CedarValueJson::Long(_) => Ok(self),
425 CedarValueJson::String(_) => Ok(self),
426 CedarValueJson::Set(v) => Ok(CedarValueJson::Set(
427 v.into_iter()
428 .map(|e| e.sub_entity_literals(mapping))
429 .collect::<Result<Vec<_>, _>>()?,
430 )),
431 CedarValueJson::Record(r) => {
432 let mut new_m = BTreeMap::new();
433 for (k, v) in r.values {
434 new_m.insert(k, v.sub_entity_literals(mapping)?);
435 }
436 Ok(CedarValueJson::Record(JsonRecord { values: new_m }))
437 }
438 CedarValueJson::Null => Ok(self),
439 }
440 }
441}
442
443fn check_for_reserved_keys<'a>(
446 mut keys: impl Iterator<Item = &'a SmolStr>,
447) -> Result<(), JsonSerializationError> {
448 let reserved_keys: HashSet<&str> = HashSet::from_iter(["__entity", "__extn", "__expr"]);
453 let collision = keys.find(|k| reserved_keys.contains(k.as_str()));
454 match collision {
455 Some(collision) => Err(JsonSerializationError::reserved_key(collision.clone())),
456 None => Ok(()),
457 }
458}
459
460impl FnAndArg {
461 pub fn into_expr(
463 self,
464 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
465 ) -> Result<RestrictedExpr, JsonDeserializationError> {
466 Ok(RestrictedExpr::call_extension_fn(
467 Name::from_normalized_str(&self.ext_fn).map_err(|errs| {
468 JsonDeserializationError::parse_escape(EscapeKind::Extension, self.ext_fn, errs)
469 })?,
470 vec![CedarValueJson::into_expr(*self.arg, ctx)?],
471 ))
472 }
473}
474
475#[derive(Debug, Clone)]
477pub struct ValueParser<'e> {
478 extensions: &'e Extensions<'e>,
480}
481
482impl<'e> ValueParser<'e> {
483 pub fn new(extensions: &'e Extensions<'e>) -> Self {
485 Self { extensions }
486 }
487
488 pub fn val_into_restricted_expr(
493 &self,
494 val: serde_json::Value,
495 expected_ty: Option<&SchemaType>,
496 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
497 ) -> Result<RestrictedExpr, JsonDeserializationError> {
498 let parse_as_unknown = |val: serde_json::Value| {
501 let extjson: ExtnValueJson = serde_json::from_value(val).ok()?;
502 match extjson {
503 ExtnValueJson::ExplicitExtnEscape {
504 __extn: FnAndArg { ext_fn, arg },
505 } if ext_fn == "unknown" => {
506 let arg = arg.into_expr(ctx.clone()).ok()?;
507 let name = arg.as_string()?;
508 Some(RestrictedExpr::unknown(Unknown::new_untyped(name.clone())))
509 }
510 _ => None, }
512 };
513 if let Some(rexpr) = parse_as_unknown(val.clone()) {
514 return Ok(rexpr);
515 }
516 match expected_ty {
518 Some(SchemaType::Entity { .. }) => {
523 let uidjson: EntityUidJson = serde_json::from_value(val)?;
524 Ok(RestrictedExpr::val(uidjson.into_euid(ctx)?))
525 }
526 Some(SchemaType::Extension { ref name, .. }) => {
531 let extjson: ExtnValueJson = serde_json::from_value(val)?;
532 self.extn_value_json_into_rexpr(extjson, name.clone(), ctx)
533 }
534 Some(expected_ty @ SchemaType::Set { element_ty }) => match val {
537 serde_json::Value::Array(elements) => Ok(RestrictedExpr::set(
538 elements
539 .into_iter()
540 .map(|element| {
541 self.val_into_restricted_expr(element, Some(element_ty), ctx.clone())
542 })
543 .collect::<Result<Vec<RestrictedExpr>, JsonDeserializationError>>()?,
544 )),
545 val => {
546 let actual_val = {
547 let jvalue: CedarValueJson = serde_json::from_value(val)?;
548 jvalue.into_expr(ctx.clone())?
549 };
550 let err = TypeMismatchError::type_mismatch(
551 expected_ty.clone(),
552 actual_val.try_type_of(self.extensions),
553 actual_val,
554 );
555 match ctx() {
556 JsonDeserializationErrorContext::EntityAttribute { uid, attr } => {
557 Err(JsonDeserializationError::EntitySchemaConformance(
558 EntitySchemaConformanceError::type_mismatch(uid, attr, err),
559 ))
560 }
561 ctx => Err(JsonDeserializationError::type_mismatch(ctx, err)),
562 }
563 }
564 },
565 Some(
569 expected_ty @ SchemaType::Record {
570 attrs: expected_attrs,
571 open_attrs,
572 },
573 ) => match val {
574 serde_json::Value::Object(mut actual_attrs) => {
575 let ctx2 = ctx.clone(); let mut_actual_attrs = &mut actual_attrs; let rexpr_pairs = expected_attrs
578 .iter()
579 .filter_map(move |(k, expected_attr_ty)| {
580 match mut_actual_attrs.remove(k.as_str()) {
581 Some(actual_attr) => {
582 match self.val_into_restricted_expr(actual_attr, Some(expected_attr_ty.schema_type()), ctx.clone()) {
583 Ok(actual_attr) => Some(Ok((k.clone(), actual_attr))),
584 Err(e) => Some(Err(e)),
585 }
586 }
587 None if expected_attr_ty.is_required() => Some(Err(JsonDeserializationError::missing_required_record_attr(ctx(), k.clone()))),
588 None => None,
589 }
590 })
591 .collect::<Result<Vec<(SmolStr, RestrictedExpr)>, JsonDeserializationError>>()?;
592
593 if !open_attrs {
594 if let Some((record_attr, _)) = actual_attrs.into_iter().next() {
597 return Err(JsonDeserializationError::unexpected_record_attr(
598 ctx2(),
599 record_attr,
600 ));
601 }
602 }
603
604 RestrictedExpr::record(rexpr_pairs).map_err(|e| match e {
609 ExpressionConstructionError::DuplicateKey(
610 expression_construction_errors::DuplicateKeyError { key, .. },
611 ) => JsonDeserializationError::duplicate_key(ctx2(), key),
612 })
613 }
614 val => {
615 let actual_val = {
616 let jvalue: CedarValueJson = serde_json::from_value(val)?;
617 jvalue.into_expr(ctx.clone())?
618 };
619 let err = TypeMismatchError::type_mismatch(
620 expected_ty.clone(),
621 actual_val.try_type_of(self.extensions),
622 actual_val,
623 );
624 match ctx() {
625 JsonDeserializationErrorContext::EntityAttribute { uid, attr } => {
626 Err(JsonDeserializationError::EntitySchemaConformance(
627 EntitySchemaConformanceError::type_mismatch(uid, attr, err),
628 ))
629 }
630 ctx => Err(JsonDeserializationError::type_mismatch(ctx, err)),
631 }
632 }
633 },
634 Some(_) | None => {
637 let jvalue: CedarValueJson = serde_json::from_value(val)?;
640 Ok(jvalue.into_expr(ctx)?)
641 }
642 }
643 }
644
645 fn extn_value_json_into_rexpr(
650 &self,
651 extnjson: ExtnValueJson,
652 expected_typename: Name,
653 ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
654 ) -> Result<RestrictedExpr, JsonDeserializationError> {
655 match extnjson {
656 ExtnValueJson::ExplicitExprEscape { __expr } => {
657 Err(JsonDeserializationError::ExprTag(Box::new(ctx())))
658 }
659 ExtnValueJson::ExplicitExtnEscape { __extn }
660 | ExtnValueJson::ImplicitExtnEscape(__extn) => {
661 let jvalue = CedarValueJson::ExtnEscape { __extn };
663 let expr = jvalue.into_expr(ctx.clone())?;
664 match expr.expr_kind() {
665 ExprKind::ExtensionFunctionApp { .. } => Ok(expr),
666 _ => Err(JsonDeserializationError::expected_extn_value(
667 ctx(),
668 Either::Right(expr.clone().into()),
669 )),
670 }
671 }
672 ExtnValueJson::ImplicitConstructor(val) => {
673 let expected_return_type = SchemaType::Extension {
674 name: expected_typename,
675 };
676 let func = self
677 .extensions
678 .lookup_single_arg_constructor(&expected_return_type)
679 .ok_or_else(|| {
680 JsonDeserializationError::missing_implied_constructor(
681 ctx(),
682 expected_return_type,
683 )
684 })?;
685 let arg = val.into_expr(ctx.clone())?;
686 Ok(RestrictedExpr::call_extension_fn(
687 func.name().clone(),
688 vec![arg],
689 ))
690 }
691 }
692 }
693}
694
695pub trait DeserializationContext {
699 fn static_context() -> Option<JsonDeserializationErrorContext>;
702}
703
704#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
707pub struct NoStaticContext;
708
709impl DeserializationContext for NoStaticContext {
710 fn static_context() -> Option<JsonDeserializationErrorContext> {
711 None
712 }
713}
714
715#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
718#[serde(untagged)]
719#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
720#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
721pub enum EntityUidJson<Context = NoStaticContext> {
722 ExplicitExprEscape {
724 #[cfg_attr(feature = "wasm", tsify(type = "__skip"))]
726 __expr: String,
727 #[serde(skip)]
729 context: std::marker::PhantomData<Context>,
730 },
731 ExplicitEntityEscape {
733 __entity: TypeAndId,
735 },
736 ImplicitEntityEscape(TypeAndId),
739
740 FoundValue(#[cfg_attr(feature = "wasm", tsify(type = "__skip"))] serde_json::Value),
742}
743
744impl<'de, C: DeserializationContext> DeserializeAs<'de, EntityUID> for EntityUidJson<C> {
745 fn deserialize_as<D>(deserializer: D) -> Result<EntityUID, D::Error>
746 where
747 D: serde::Deserializer<'de>,
748 {
749 use serde::de::Error;
750 let context = || JsonDeserializationErrorContext::Unknown;
752 let s = EntityUidJson::<C>::deserialize(deserializer)?;
753 let euid = s.into_euid(context).map_err(Error::custom)?;
754 Ok(euid)
755 }
756}
757
758impl<C> SerializeAs<EntityUID> for EntityUidJson<C> {
759 fn serialize_as<S>(source: &EntityUID, serializer: S) -> Result<S::Ok, S::Error>
760 where
761 S: serde::Serializer,
762 {
763 let json: EntityUidJson = source.clone().into();
764 json.serialize(serializer)
765 }
766}
767
768impl<C: DeserializationContext> EntityUidJson<C> {
769 pub fn new(entity_type: impl Into<SmolStr>, id: impl Into<SmolStr>) -> Self {
773 Self::ImplicitEntityEscape(TypeAndId {
774 entity_type: entity_type.into(),
775 id: id.into(),
776 })
777 }
778
779 pub fn into_euid(
781 self,
782 dynamic_ctx: impl Fn() -> JsonDeserializationErrorContext + Clone,
783 ) -> Result<EntityUID, JsonDeserializationError> {
784 let ctx = || C::static_context().unwrap_or_else(&dynamic_ctx);
785 match self {
786 Self::ExplicitEntityEscape { __entity } | Self::ImplicitEntityEscape(__entity) => {
787 let jvalue = CedarValueJson::EntityEscape { __entity };
789 let expr = jvalue.into_expr(ctx)?;
790 match expr.expr_kind() {
791 ExprKind::Lit(Literal::EntityUID(euid)) => Ok((**euid).clone()),
792 _ => Err(JsonDeserializationError::expected_entity_ref(
793 ctx(),
794 Either::Right(expr.clone().into()),
795 )),
796 }
797 }
798 Self::FoundValue(v) => Err(JsonDeserializationError::expected_entity_ref(
799 ctx(),
800 Either::Left(v),
801 )),
802 Self::ExplicitExprEscape { __expr, .. } => {
803 Err(JsonDeserializationError::ExprTag(Box::new(ctx())))
804 }
805 }
806 }
807}
808
809impl From<EntityUID> for EntityUidJson {
811 fn from(uid: EntityUID) -> EntityUidJson {
812 EntityUidJson::ExplicitEntityEscape {
813 __entity: uid.into(),
814 }
815 }
816}
817
818impl From<&EntityUID> for EntityUidJson {
820 fn from(uid: &EntityUID) -> EntityUidJson {
821 EntityUidJson::ExplicitEntityEscape {
822 __entity: uid.into(),
823 }
824 }
825}
826
827#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
830#[serde(untagged)]
831pub enum ExtnValueJson {
832 ExplicitExprEscape {
834 __expr: String,
836 },
837 ExplicitExtnEscape {
839 __extn: FnAndArg,
841 },
842 ImplicitExtnEscape(FnAndArg),
845 ImplicitConstructor(CedarValueJson),
851}