use crate::ExpectJsonError;
use crate::JsonType;
use crate::expect_core::Context;
use crate::expect_core::ExpectOp;
use crate::internals::ExpectOpMeta;
use crate::internals::objects::ArrayObject;
use crate::internals::objects::FloatObject;
use crate::internals::objects::IntegerObject;
use crate::internals::objects::ValueObject;
use crate::internals::objects::ValueTypeObject;
use std::error::Error as StdError;
use thiserror::Error;
pub type ExpectOpResult<V> = Result<V, ExpectOpError>;
#[derive(Debug, Error)]
pub enum ExpectOpError {
#[error(
"Json expect::{}() at {context}, received wrong type:
expected {}
received {received}",
expected_operation.name,
format_expected_operation_types(expected_operation),
)]
UnsupportedOperation {
context: Context<'static>,
received: ValueTypeObject,
expected_operation: ExpectOpMeta,
},
#[error(
"Json object at {context} is missing key for {}:
expected field '{expected_key}',
but it was not found",
expected_operation.name
)]
ObjectKeyMissingForExpectOp {
context: Context<'static>,
expected_key: String,
expected_operation: ExpectOpMeta,
},
#[error(
"Json at {context} has key with value, expecting either key not present or different value.
received {received}"
)]
ObjectKeyValueIsEqual {
context: Context<'static>,
received: ValueObject,
expected_operation: ExpectOpMeta,
},
#[error(
"Json {json_type} at {context} contains value was expecting to not be there:
expected {json_type} to not contain {expected}, but it was found.
received {received}"
)]
ContainsFound {
context: Context<'static>,
json_type: JsonType,
expected: ValueObject,
received: ValueObject,
},
#[error(
"Json {json_type} at {context} does not contain expected value:
expected {json_type} to contain {expected}, but it was not found.
received {received}"
)]
ContainsNotFound {
context: Context<'static>,
json_type: JsonType,
expected: ValueObject,
received: ValueObject,
},
#[error(
"Json {json_type} error at {context}, regex did not match:
expected {json_type} to match regex pattern '{pattern}',
received {received}"
)]
RegexNoMatch {
context: Context<'static>,
json_type: JsonType,
pattern: String,
received: ValueObject,
},
#[error(
"Json expect::array() error at {context},
expected array to contain all unique values.
found duplicate {duplicate}
received full array {received_array}"
)]
ArrayContainsDuplicate {
context: Context<'static>,
duplicate: ValueObject,
received_array: ArrayObject,
},
#[error(
"{error}
received full array {received_full_array}"
)]
ArrayAllEqual {
#[source]
error: Box<ExpectJsonError>,
received_full_array: ArrayObject,
},
#[error(
"Json expect::array() error at {context}, mismatch:
expected array (up to order): {expected_array},
received array: {received_array}"
)]
ArrayUnorderedMismatch {
context: Context<'static>,
expected_array: ArrayObject,
received_array: ArrayObject,
},
#[error(
"Json expect::integer() error at {context}, is zero:
expected non-zero integer
received {received}"
)]
IntegerIsZero {
context: Context<'static>,
received: IntegerObject,
},
#[error(
"Json expect::integer() error at {context}, is not zero:
expected 0
received {received}"
)]
IntegerIsNotZero {
context: Context<'static>,
received: IntegerObject,
},
#[error(
"Json expect::float() error at {context}, is zero:
expected non-zero float
received {received}"
)]
FloatIsZero {
context: Context<'static>,
received: FloatObject,
},
#[error(
"Json expect::float() error at {context}, is not zero:
expected 0.0
received {received}"
)]
FloatIsNotZero {
context: Context<'static>,
received: FloatObject,
},
#[error(
"Json expect::{}() error at {context}:
{message},
{error}",
expected_operation.name,
)]
UnknownError {
#[source]
error: Box<dyn StdError>,
context: Context<'static>,
message: String,
expected_operation: ExpectOpMeta,
},
#[error(
"Json expect::{}() error at {context}:
{message}",
expected_operation.name,
)]
UnknownErrorMessage {
context: Context<'static>,
message: String,
expected_operation: ExpectOpMeta,
},
#[error("{error}")]
ExpectJsonError {
#[source]
error: Box<ExpectJsonError>,
},
}
impl ExpectOpError {
pub fn custom<O, S>(expect_op: &O, context: &Context<'_>, message: S) -> Self
where
O: ExpectOp + ?Sized,
S: Into<String>,
{
Self::UnknownErrorMessage {
context: context.to_static(),
message: message.into(),
expected_operation: ExpectOpMeta::new(expect_op),
}
}
pub fn custom_error<O, S, E>(expect_op: &O, context: &Context<'_>, message: S, error: E) -> Self
where
O: ExpectOp + ?Sized,
S: Into<String>,
E: StdError + 'static,
{
Self::UnknownError {
context: context.to_static(),
error: Box::new(error),
message: message.into(),
expected_operation: ExpectOpMeta::new(expect_op),
}
}
pub fn unsupported_operation_type<O, V>(
context: &Context<'_>,
expect_op: &O,
received: V,
) -> Self
where
O: ExpectOp + ?Sized,
V: Into<ValueTypeObject>,
{
Self::UnsupportedOperation {
context: context.to_static(),
received: received.into(),
expected_operation: ExpectOpMeta::new(expect_op),
}
}
}
impl From<ExpectJsonError> for ExpectOpError {
fn from(error: ExpectJsonError) -> Self {
Self::ExpectJsonError {
error: Box::new(error),
}
}
}
fn format_expected_operation_types(expected_operation: &ExpectOpMeta) -> String {
let types = expected_operation.types;
if types.is_empty() {
return "no supported types listed (need to implement ExpectOp::supported_types)"
.to_string();
}
types.join(", ")
}