use crate::ExpectJsonError;
use crate::ExpectJsonResult;
use crate::expect_core::Context;
use crate::internals::objects::ArrayObject;
use serde_json::Value;
pub fn json_value_eq_array<'a>(
context: &mut Context<'a>,
received_array: &'a [Value],
expected_array: &'a [Value],
) -> ExpectJsonResult<()> {
if expected_array.len() > received_array.len() {
if let Some(missing_in_received) = has_more_at_end(received_array, expected_array) {
return Err(ExpectJsonError::ArrayMissingAtEnd {
context: context.to_static(),
received_array: ArrayObject::from(received_array.to_owned()),
expected_array: ArrayObject::from(expected_array.to_owned()),
missing_in_received: ArrayObject::from(missing_in_received),
});
}
if let Some(missing_in_received) = has_more_at_start(received_array, expected_array) {
return Err(ExpectJsonError::ArrayMissingAtStart {
context: context.to_static(),
received_array: ArrayObject::from(received_array.to_owned()),
expected_array: ArrayObject::from(expected_array.to_owned()),
missing_in_received: ArrayObject::from(missing_in_received),
});
}
return Err(ExpectJsonError::ArrayMissingInMiddle {
context: context.to_static(),
received_array: ArrayObject::from(received_array.to_owned()),
expected_array: ArrayObject::from(expected_array.to_owned()),
});
}
if expected_array.len() < received_array.len() {
if let Some(extra_in_received) = has_more_at_end(expected_array, received_array) {
return Err(ExpectJsonError::ArrayExtraAtEnd {
context: context.to_static(),
received_array: ArrayObject::from(received_array.to_owned()),
expected_array: ArrayObject::from(expected_array.to_owned()),
extra_in_received: ArrayObject::from(extra_in_received),
});
}
if let Some(extra_in_received) = has_more_at_start(expected_array, received_array) {
return Err(ExpectJsonError::ArrayExtraAtStart {
context: context.to_static(),
received_array: ArrayObject::from(received_array.to_owned()),
expected_array: ArrayObject::from(expected_array.to_owned()),
extra_in_received: ArrayObject::from(extra_in_received),
});
}
return Err(ExpectJsonError::ArrayValuesAreDifferent {
context: context.to_static(),
received_array: ArrayObject::from(received_array.to_owned()),
expected_array: ArrayObject::from(expected_array.to_owned()),
});
}
for (index, (expected_value, received_value)) in
expected_array.iter().zip(received_array).enumerate()
{
context
.with_path(index)
.json_eq(received_value, expected_value)
.map_err(|source_error| {
ExpectJsonError::array_index_missing(
context,
source_error,
received_array,
expected_array,
)
})?;
}
Ok(())
}
fn has_more_at_end<'a>(
left: &'a [Value],
right: &'a [Value],
) -> Option<impl Iterator<Item = Value> + 'a> {
let mut zipped_arrays_at_start = left.iter().zip(right);
let is_all_equal_at_start = zipped_arrays_at_start.all(|(left, right)| left == right);
if is_all_equal_at_start {
let missing_in_left = right[left.len()..].iter().cloned();
return Some(missing_in_left);
}
None
}
fn has_more_at_start<'a>(
left: &'a [Value],
right: &'a [Value],
) -> Option<impl Iterator<Item = Value> + 'a> {
let mut zipped_arrays_at_end = left.iter().rev().zip(right.iter().rev());
let is_all_equal_at_end = zipped_arrays_at_end.all(|(left, right)| left == right);
if is_all_equal_at_end {
let len_diff = right.len() - left.len();
let missing_in_left = right[0..len_diff].iter().cloned();
return Some(missing_in_left);
}
None
}