use super::*;
use crate::composition_objects::TextExt;
use paste::paste;
type List<T> = Value<Vec<T>>;
fn inner_validator<T>(
mut value: List<T>,
error: ValidationErrorKind,
predicate: impl Fn(&[T]) -> bool,
) -> List<T> {
if value.inner_ref().is_some_and(|v| predicate(v.as_ref())) {
value.push(error);
}
value
}
fn max_item<T>(max: usize, value: List<T>) -> List<T> {
inner_validator(value, ValidationErrorKind::MaxArraySize(max), |l| {
l.len() > max
})
}
macro_rules! impl_max_item {
($($e:expr),*) => {
paste! {
$(
pub(crate) fn [<max_item_ $e>]<T>(value: List<T>) -> List<T> {
max_item($e, value)
}
)*
}
}
}
impl_max_item!(5, 10, 20, 25, 50, 100);
pub(crate) fn not_empty<T>(value: List<T>) -> List<T> {
inner_validator(value, ValidationErrorKind::EmptyArray, |l| l.is_empty())
}
pub(crate) fn each_text_max_2000<T: TextExt>(value: List<T>) -> List<T> {
inner_validator(value, ValidationErrorKind::MaxTextLength(2000), |l| {
l.iter()
.any(|t| t.text().is_some_and(|text| text.len() > 2000))
})
}
#[cfg(test)]
mod tests {
use super::*;
mod fn_max_item_100 {
use super::*;
#[test]
fn it_passes_if_the_list_length_is_smaller_than_100() {
let list: Vec<u8> = (0..100).collect();
let result = test(list);
assert!(result.errors.is_empty());
}
#[test]
fn it_sets_an_error_if_the_list_length_is_greater_than_101() {
let list: Vec<u8> = (0..101).collect();
let result = test(list);
assert_eq!(result.errors, vec![ValidationErrorKind::MaxArraySize(100)]);
}
fn test<T>(list: Vec<T>) -> List<T> {
max_item_100(Value::new(Some(list)))
}
}
mod fn_not_empty {
use super::*;
#[test]
fn it_passes_if_the_list_is_not_empty() {
let list: Vec<u8> = vec![0];
let result = test(list);
assert!(result.errors.is_empty());
}
#[test]
fn it_sets_an_error_if_the_list_is_empty() {
let list: Vec<u8> = vec![];
let result = test(list);
assert_eq!(result.errors, vec![ValidationErrorKind::EmptyArray]);
}
fn test<T>(list: Vec<T>) -> List<T> {
not_empty(Value::new(Some(list)))
}
}
mod fn_each_text_max_2000 {
use super::*;
use crate::composition_objects::{Plain, Text};
#[test]
fn it_passes_if_the_all_text_length_is_less_than_2000() {
let list = vec!["a".repeat(2000), "foobar".into()];
let result = test(list);
assert!(result.errors.is_empty());
}
#[test]
fn it_sets_an_error_if_at_least_one_text_length_is_more_than_2000() {
let list = vec!["a".repeat(2001), "foobar".into()];
let result = test(list);
assert_eq!(
result.errors,
vec![ValidationErrorKind::MaxTextLength(2000)]
);
}
fn test(list: Vec<String>) -> List<Text<Plain>> {
let list = list
.into_iter()
.map(|text| Text::builder().text(text).build().unwrap())
.collect();
each_text_max_2000(Value::new(Some(list)))
}
}
}