use crate::{Expression, FunctionCall, Identifier, Literal, TemplateChunk};
use bytes::Bytes;
use indexmap::IndexMap;
use proptest::{
collection,
prelude::{Arbitrary, Strategy, any},
prop_oneof,
sample::SizeRange,
};
use std::hash::Hash;
pub fn bytes() -> impl Strategy<Value = Bytes> {
any::<Vec<u8>>().prop_map(Bytes::from)
}
pub fn join_raw(chunks: Vec<TemplateChunk>) -> Vec<TemplateChunk> {
let len = chunks.len();
chunks
.into_iter()
.fold(Vec::with_capacity(len), |mut chunks, chunk| {
match (chunks.last_mut(), chunk) {
(
Some(TemplateChunk::Raw(previous)),
TemplateChunk::Raw(current),
) => {
let mut concat =
String::with_capacity(previous.len() + current.len());
concat.push_str(previous);
concat.push_str(¤t);
*previous = concat.into();
}
(_, chunk) => chunks.push(chunk),
}
chunks
})
}
pub fn expression_arbitrary() -> impl Strategy<Value = Expression> {
let leaf = prop_oneof![
any::<Literal>().prop_map(Expression::Literal),
any::<Identifier>().prop_map(Expression::Field),
];
leaf.prop_recursive(2, 10, 2, |inner| {
prop_oneof![
collection::vec(inner.clone(), 0..=2).prop_map(Expression::Array),
(
Identifier::arbitrary(),
collection::vec(inner.clone(), 0..=1),
collection::hash_map(
Identifier::arbitrary(),
inner.clone(),
0..=1
)
)
.prop_map(|(function, position, keyword)| {
Expression::Call(FunctionCall {
function,
position,
keyword: keyword.into_iter().collect(),
})
}),
]
})
}
pub fn index_map<K: Strategy, V: Strategy>(
key: K,
value: V,
size: impl Into<SizeRange>,
) -> impl Strategy<Value = IndexMap<K::Value, V::Value>>
where
K::Value: Hash + Eq,
{
collection::hash_map(key, value, size)
.prop_map(|map| map.into_iter().collect())
}