use std::fmt::Display;
use super::SchemaType;
use crate::ast::{
EntityType, EntityUID, Expr, ExprKind, Name, RestrictedExpr, RestrictedExpressionError,
};
use crate::extensions::ExtensionsError;
use crate::parser::err::ParseErrors;
use smol_str::SmolStr;
use thiserror::Error;
#[derive(Debug)]
pub enum EscapeKind {
Expr,
Entity,
Extension,
}
impl Display for EscapeKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Entity => write!(f, "__entity"),
Self::Expr => write!(f, "__expr"),
Self::Extension => write!(f, "__extn"),
}
}
}
#[derive(Debug, Error)]
pub enum JsonDeserializationError {
#[error("{0}")]
Serde(#[from] serde_json::Error),
#[error("failed to parse escape `{kind}`: {value}, errors: {errs}")]
ParseEscape {
kind: EscapeKind,
value: String,
errs: ParseErrors,
},
#[error(transparent)]
RestrictedExpressionError(#[from] RestrictedExpressionError),
#[error(transparent)]
ExtensionsError(#[from] ExtensionsError),
#[error("{ctx}, expected a literal entity reference, but got: {got}")]
ExpectedLiteralEntityRef {
ctx: Box<JsonDeserializationErrorContext>,
got: Box<Expr>,
},
#[error("{ctx}, expected an extension value, but got: {got}")]
ExpectedExtnValue {
ctx: Box<JsonDeserializationErrorContext>,
got: Box<Expr>,
},
#[error("expected `context` to be a record, but got `{got}`")]
ExpectedContextToBeRecord {
got: Box<RestrictedExpr>,
},
#[error("action `{uid}` has a non-action parent `{parent}`")]
ActionParentIsNotAction {
uid: EntityUID,
parent: EntityUID,
},
#[error("{ctx}, missing extension constructor for {arg_type} -> {return_type}")]
MissingImpliedConstructor {
ctx: Box<JsonDeserializationErrorContext>,
return_type: Box<SchemaType>,
arg_type: Box<SchemaType>,
},
#[error("entity `{uid}` has type `{}` which is not declared in the schema{}",
&.uid.entity_type(),
match .suggested_types.as_slice() {
[] => String::new(),
[ty] => format!("; did you mean {ty}?"),
tys => format!("; did you mean one of {:?}?", tys.iter().map(ToString::to_string).collect::<Vec<String>>())
}
)]
UnexpectedEntityType {
uid: EntityUID,
suggested_types: Vec<EntityType>,
},
#[error("found action entity `{uid}`, but it was not declared as an action in the schema")]
UndeclaredAction {
uid: EntityUID,
},
#[error("definition of action `{uid}` does not match its schema declaration")]
ActionDeclarationMismatch {
uid: EntityUID,
},
#[error("attribute {:?} on `{uid}` shouldn't exist according to the schema", &.attr)]
UnexpectedEntityAttr {
uid: EntityUID,
attr: SmolStr,
},
#[error("{ctx}, record attribute {record_attr:?} shouldn't exist according to the schema")]
UnexpectedRecordAttr {
ctx: Box<JsonDeserializationErrorContext>,
record_attr: SmolStr,
},
#[error("expected entity `{uid}` to have an attribute {attr:?}, but it doesn't")]
MissingRequiredEntityAttr {
uid: EntityUID,
attr: SmolStr,
},
#[error("{ctx}, expected the record to have an attribute {record_attr:?}, but it doesn't")]
MissingRequiredRecordAttr {
ctx: Box<JsonDeserializationErrorContext>,
record_attr: SmolStr,
},
#[error("{ctx}, type mismatch: attribute was expected to have type {expected}, but actually has type {actual}")]
TypeMismatch {
ctx: Box<JsonDeserializationErrorContext>,
expected: Box<SchemaType>,
actual: Box<SchemaType>,
},
#[error("{ctx}, set elements have different types: {ty1} and {ty2}")]
HeterogeneousSet {
ctx: Box<JsonDeserializationErrorContext>,
ty1: Box<SchemaType>,
ty2: Box<SchemaType>,
},
#[error(
"{ctx}, `{uid}` is not allowed to have a parent of type `{parent_ty}` according to the schema"
)]
InvalidParentType {
ctx: Box<JsonDeserializationErrorContext>,
uid: EntityUID,
parent_ty: Box<EntityType>, },
}
#[derive(Debug, Error)]
pub enum JsonSerializationError {
#[error("{0}")]
Serde(#[from] serde_json::Error),
#[error("extension-function calls with 0 arguments are not currently supported in our JSON format. found call of {func}")]
ExtnCall0Arguments {
func: Name,
},
#[error("extension-function calls with 2 or more arguments are not currently supported in our JSON format. found call of {func}")]
ExtnCall2OrMoreArguments {
func: Name,
},
#[error("record uses reserved key: {key}")]
ReservedKey {
key: SmolStr,
},
#[error("unexpected restricted expression: {kind:?}")]
UnexpectedRestrictedExprKind {
kind: ExprKind,
},
}
#[derive(Debug, Clone)]
pub enum JsonDeserializationErrorContext {
EntityAttribute {
uid: EntityUID,
attr: SmolStr,
},
EntityParents {
uid: EntityUID,
},
EntityUid,
Context,
}
impl std::fmt::Display for JsonDeserializationErrorContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::EntityAttribute { uid, attr } => write!(f, "in attribute {attr:?} on {uid}"),
Self::EntityParents { uid } => write!(f, "in parents field of {uid}"),
Self::EntityUid => write!(f, "in uid field of <unknown entity>"),
Self::Context => write!(f, "while parsing context"),
}
}
}