use super::{pair_bytes, sig, triple_bytes, u32_bytes, InputGenerator};
use crate::spec::types::OpSignature;
pub struct EdgeCases;
impl InputGenerator for EdgeCases {
fn name(&self) -> &'static str {
"edge_cases"
}
fn handles(&self, signature: &OpSignature) -> bool {
sig::is_u32_any(signature)
}
fn generate(&self, signature: &OpSignature, _seed: u64) -> Vec<(String, Vec<u8>)> {
let values = edge_values();
if sig::is_unary_u32(signature) {
values
.iter()
.map(|value| (format!("edge:{value:#010x}"), u32_bytes(*value)))
.collect()
} else if sig::is_binary_u32(signature) {
let mut out = Vec::with_capacity(values.len() * values.len());
for left in &values {
for right in &values {
out.push((
format!("edge_pair:{left:#010x}:{right:#010x}"),
pair_bytes(*left, *right),
));
}
}
out
} else if sig::is_ternary_u32(signature) {
let triples = [
(0, 0, 0),
(0, 1, u32::MAX),
(u32::MAX, 1, 0),
(0x8000_0000, 31, 32),
(0x5555_5555, 0xAAAA_AAAA, 0xFFFF_0000),
];
triples
.into_iter()
.map(|(a, b, c)| {
(
format!("edge_triple:{a:#010x}:{b:#010x}:{c:#010x}"),
triple_bytes(a, b, c),
)
})
.collect()
} else {
Vec::new()
}
}
}
fn edge_values() -> Vec<u32> {
let mut values = vec![
0,
1,
u32::MAX,
u32::MAX - 1,
0x5555_5555,
0xAAAA_AAAA,
0x8000_0000,
2,
3,
5,
7,
11,
13,
17,
19,
23,
29,
31,
65_521,
65_537,
0x0000_FFFF,
0x0001_0000,
0x0001_0001,
0x7FFF_FFFF,
0x8000_0001,
i32::MIN as u32,
i32::MIN.wrapping_add(1) as u32,
i32::MAX as u32,
i32::MAX.wrapping_sub(1) as u32,
];
for shift in 0..32 {
values.push(1_u32 << shift);
}
values.sort_unstable();
values.dedup();
values
}