use ::proptest::collection::vec;
use ::proptest::prelude::*;
use smol_str::SmolStr;
use std::sync::LazyLock;
use crate::Hugr;
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct RecursionDepth(usize);
impl RecursionDepth {
const DEFAULT_RECURSION_DEPTH: usize = 4;
#[must_use]
pub fn descend(&self) -> Self {
if self.leaf() { *self } else { Self(self.0 - 1) }
}
#[must_use]
pub fn leaf(&self) -> bool {
self.0 == 0
}
#[must_use]
pub fn new() -> Self {
Self(Self::DEFAULT_RECURSION_DEPTH)
}
}
impl Default for RecursionDepth {
fn default() -> Self {
Self::new()
}
}
impl<I: TryInto<usize>> From<I> for RecursionDepth
where
<I as TryInto<usize>>::Error: std::fmt::Debug,
{
fn from(s: I) -> Self {
Self(s.try_into().unwrap())
}
}
static ANY_IDENT_STRING: LazyLock<SBoxedStrategy<String>> = LazyLock::new(|| {
use proptest::string::string_regex;
prop_oneof![
string_regex(r"[[:alpha:]]+").unwrap(),
string_regex(crate::hugr::ident::PATH_COMPONENT_REGEX_STR).unwrap(),
]
.sboxed()
});
static ANY_NONEMPTY_STRING: LazyLock<SBoxedStrategy<String>> = LazyLock::new(|| {
use proptest::string::string_regex;
prop_oneof![
string_regex(r"[[:alpha:]]+").unwrap(),
string_regex(r".+").unwrap(),
]
.sboxed()
});
static ANY_STRING: LazyLock<SBoxedStrategy<String>> = LazyLock::new(|| {
use proptest::string::string_regex;
prop_oneof![
string_regex(r"[[:alpha:]]*").unwrap(),
string_regex(r".*").unwrap(),
]
.sboxed()
});
static ANY_SERDE_JSON_VALUE_LEAF: LazyLock<SBoxedStrategy<serde_json::Value>> =
LazyLock::new(|| {
use serde_json::value::Value;
prop_oneof![
Just(Value::Null),
any::<bool>().prop_map_into(),
any::<u64>().prop_map_into(),
any::<i64>().prop_map_into(),
Just(Value::Number(3.into())),
any_string().prop_map_into(),
]
.sboxed()
});
static ANY_HUGR: LazyLock<SBoxedStrategy<Hugr>> = LazyLock::new(|| {
prop_oneof![Just(crate::builder::test::simple_dfg_hugr()),].sboxed()
});
pub fn any_nonempty_string() -> SBoxedStrategy<String> {
ANY_NONEMPTY_STRING.to_owned()
}
pub fn any_nonempty_smolstr() -> SBoxedStrategy<SmolStr> {
ANY_NONEMPTY_STRING.to_owned().prop_map_into().sboxed()
}
pub fn any_ident_string() -> SBoxedStrategy<String> {
ANY_IDENT_STRING.to_owned()
}
pub fn any_string() -> SBoxedStrategy<String> {
ANY_STRING.to_owned()
}
pub fn any_smolstr() -> SBoxedStrategy<SmolStr> {
ANY_STRING.clone().prop_map_into().sboxed()
}
pub fn any_serde_json_value() -> impl Strategy<Value = serde_json::Value> {
ANY_SERDE_JSON_VALUE_LEAF
.clone()
.prop_recursive(
3, 32, 3, |element| {
prop_oneof![
proptest::collection::vec(element.clone(), 0..3).prop_map_into(),
vec((any_string().prop_map_into(), element.clone()), 0..3).prop_map(|x| x
.into_iter()
.collect::<serde_json::Map<String, serde_json::Value>>()
.into())
]
},
)
.boxed()
}
pub fn any_hugr() -> SBoxedStrategy<Hugr> {
ANY_HUGR.to_owned()
}