use {
crate::{
multiset::Multiset,
pbt::{
Algebraic, ArbitraryFn, CtorFn, Decomposition, ElimFn, IntroductionRule, Literal, Pbt,
TypeFormer, try_arbitrary_field, visit_self, visit_self_opt,
},
reflection::{TermsOfVariousTypes, Type, register, type_of},
scc::StronglyConnectedComponents,
shrink::shrink,
},
alloc::{collections::BTreeSet, ffi::CString},
core::{iter, mem, num::NonZero},
};
impl Pbt for char {
#[inline]
#[expect(
clippy::needless_return,
reason = "in case a function body is added later"
)]
fn register_all_immediate_dependencies(
visited: &mut BTreeSet<Type>,
_sccs: &mut StronglyConnectedComponents,
) {
if !visited.insert(type_of::<Self>()) {
return;
}
}
#[inline]
#[expect(
clippy::as_conversions,
clippy::cast_possible_truncation,
reason = "intentional"
)]
fn type_former() -> TypeFormer<Self> {
TypeFormer::Literal(Literal {
deserialize: |s| s.parse().ok(),
generate: |prng| loop {
let u = prng.rand() as u32;
if let Ok(c) = char::try_from(u) {
return c;
}
},
serialize: |value: &Self| value.to_string(),
shrink: |c| Box::new(shrink(c as u32).filter_map(|u| char::try_from(u).ok())),
})
}
#[inline]
fn visit_deep<V>(&self) -> impl Iterator<Item = V>
where
V: Pbt,
{
visit_self(self)
}
}
impl Pbt for String {
#[inline]
fn register_all_immediate_dependencies(
visited: &mut BTreeSet<Type>,
sccs: &mut StronglyConnectedComponents,
) {
if !visited.insert(type_of::<Self>()) {
return;
}
let () = register::<char>(visited.clone(), sccs);
}
#[inline]
fn type_former() -> TypeFormer<Self> {
TypeFormer::Algebraic(Algebraic {
introduction_rules: Box::new([
IntroductionRule {
arbitrary: ArbitraryFn::new(|_, _, _| Ok(Some(String::new()))),
call: CtorFn::new(|_| Some(String::new())),
immediate_dependencies: Multiset::new(),
},
IntroductionRule {
arbitrary: ArbitraryFn::new(|prng, swarm, mut sizes| {
let head = try_arbitrary_field::<char>(&mut sizes, prng, swarm)?;
let mut acc = try_arbitrary_field::<Self>(&mut sizes, prng, swarm)?;
acc.push(head);
Ok(Some(acc))
}),
call: CtorFn::new(|terms| {
let mut acc = terms.must_pop::<Self>(); acc.push(terms.must_pop::<char>()); Some(acc)
}),
immediate_dependencies: [type_of::<char>(), type_of::<Self>()]
.into_iter()
.collect(),
},
]),
elimination_rule: ElimFn::new(|mut v| {
let mut fields = TermsOfVariousTypes::new();
let ctor_idx = if let Some(head) = v.pop() {
let () = fields.push::<char>(head);
let () = fields.push::<Self>(v);
2
} else {
1
};
Decomposition {
ctor_idx: unsafe { NonZero::new_unchecked(ctor_idx) },
fields,
}
}),
})
}
#[inline]
fn visit_deep<V>(&self) -> impl Iterator<Item = V>
where
V: Pbt,
{
visit_self::<V, Self>(self)
.chain(
self.chars()
.flat_map(|c| visit_self(&c).collect::<Vec<_>>()),
)
.chain({
let mut v = self.clone();
iter::from_fn(move || {
let _: char = v.pop()?;
visit_self_opt::<V, Self>(&v).cloned()
})
})
}
}
impl Pbt for CString {
#[inline]
fn register_all_immediate_dependencies(
visited: &mut BTreeSet<Type>,
sccs: &mut StronglyConnectedComponents,
) {
if !visited.insert(type_of::<Self>()) {
return;
}
let () = register::<Vec<NonZero<u8>>>(visited.clone(), sccs);
}
#[inline]
fn type_former() -> TypeFormer<Self> {
TypeFormer::Algebraic(Algebraic {
introduction_rules: Box::new([IntroductionRule {
arbitrary: ArbitraryFn::new(|prng, swarm, mut sizes| {
let nonzero_bytes =
try_arbitrary_field::<Vec<NonZero<u8>>>(&mut sizes, prng, swarm)?;
let bytes: Vec<u8> =
unsafe { mem::transmute::<Vec<NonZero<u8>>, Vec<u8>>(nonzero_bytes) };
#[expect(clippy::expect_used, reason = "logically impossible")]
Ok(Some(
CString::new(bytes).expect("internal `pbt` error: C-string error"),
))
}),
call: CtorFn::new(|terms| {
let nonzero_bytes: Vec<NonZero<u8>> = terms.must_pop();
let bytes: Vec<u8> =
unsafe { mem::transmute::<Vec<NonZero<u8>>, Vec<u8>>(nonzero_bytes) };
#[expect(clippy::expect_used, reason = "logically impossible")]
Some(CString::new(bytes).expect("internal `pbt` error: C-string error"))
}),
immediate_dependencies: iter::once(type_of::<Vec<NonZero<u8>>>()).collect(),
}]),
elimination_rule: ElimFn::new(|s| {
let mut fields = TermsOfVariousTypes::new();
let bytes = s.into_bytes();
let nonzero_bytes = unsafe { mem::transmute::<Vec<u8>, Vec<NonZero<u8>>>(bytes) };
let () = fields.push(nonzero_bytes);
Decomposition {
ctor_idx: const { NonZero::new(1).unwrap() },
fields,
}
}),
})
}
#[inline]
fn visit_deep<V>(&self) -> impl Iterator<Item = V>
where
V: Pbt,
{
visit_self::<V, Self>(self)
.chain(self.as_bytes().iter().flat_map(visit_self))
.chain({
let mut v = self.as_bytes().to_vec();
iter::from_fn(move || {
let _: u8 = v.pop()?;
visit_self_opt(&v).cloned()
})
})
}
}