use crate::JsonType;
use crate::expect::ops::ExpectString;
use crate::expect_core::Context;
use crate::expect_core::ExpectOpError;
use crate::expect_core::ExpectOpResult;
use crate::internals::objects::StringObject;
use serde::Deserialize;
use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ExpectStringSubOp {
Empty,
NotEmpty,
Len(usize),
MinLen(usize),
MaxLen(usize),
Contains(String),
MatchesRegex(String),
}
impl ExpectStringSubOp {
pub(crate) fn on_string(
&self,
parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
match self {
Self::Empty => Self::on_string_empty(parent, context, received),
Self::NotEmpty => Self::on_string_not_empty(parent, context, received),
Self::Len(len) => Self::on_string_len(*len, parent, context, received),
Self::MinLen(min_len) => Self::on_string_min_len(*min_len, parent, context, received),
Self::MaxLen(max_len) => Self::on_string_max_len(*max_len, parent, context, received),
Self::Contains(contains) => {
Self::on_string_contains(contains, parent, context, received)
}
Self::MatchesRegex(pattern) => {
Self::on_string_matches_regex(pattern, parent, context, received)
}
}
}
fn on_string_empty(
parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
if !received.is_empty() {
let error_message = format!(
r#"expected empty string
received {}"#,
StringObject::from(received)
);
return Err(ExpectOpError::custom(parent, context, error_message));
}
Ok(())
}
fn on_string_not_empty(
parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
if received.is_empty() {
let error_message = format!(
r#"expected non-empty string
received {}"#,
StringObject::from(received)
);
return Err(ExpectOpError::custom(parent, context, error_message));
}
Ok(())
}
fn on_string_len(
len: usize,
parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
if received.len() != len {
let error_message = format!(
r#"expected string to have {} characters, but it has {},
received {}"#,
len,
received.len(),
StringObject::from(received),
);
return Err(ExpectOpError::custom(parent, context, error_message));
}
Ok(())
}
fn on_string_min_len(
min_len: usize,
parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
if received.len() < min_len {
let error_message = format!(
r#"expected string to have at least {} characters, but it has {},
received {}"#,
min_len,
received.len(),
StringObject::from(received),
);
return Err(ExpectOpError::custom(parent, context, error_message));
}
Ok(())
}
fn on_string_max_len(
max_len: usize,
parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
if received.len() > max_len {
let error_message = format!(
r#"expected string to have at most {} characters, but it has {},
received {}"#,
max_len,
received.len(),
StringObject::from(received),
);
return Err(ExpectOpError::custom(parent, context, error_message));
}
Ok(())
}
fn on_string_contains(
expected_sub_string: &str,
_parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
if !received.contains(expected_sub_string) {
return Err(ExpectOpError::ContainsNotFound {
context: context.to_static(),
json_type: JsonType::String,
expected: StringObject::from(expected_sub_string).into(),
received: StringObject::from(received).into(),
});
}
Ok(())
}
fn on_string_matches_regex(
pattern: &str,
_parent: &ExpectString,
context: &mut Context<'_>,
received: &str,
) -> ExpectOpResult<()> {
let regex = regex::Regex::new(pattern).map_err(|e| {
ExpectOpError::custom(
_parent,
context,
format!("invalid regex pattern '{}': {}", pattern, e),
)
})?;
if !regex.is_match(received) {
return Err(ExpectOpError::RegexNoMatch {
context: context.to_static(),
json_type: JsonType::String,
pattern: pattern.to_string(),
received: StringObject::from(received).into(),
});
}
Ok(())
}
}