use super::bitmask::try_set_bit;
use super::ExplodedDecodeError;
use vyre_primitives::graph::exploded::decode_node;
pub fn exploded_reachability_to_statement_mask(
encoded_nodes: &[u32],
blocks_per_proc: u32,
block_to_statement: &[u32],
fact_filter: Option<u32>,
statement_count: u32,
) -> Result<Vec<u32>, ExplodedDecodeError> {
if blocks_per_proc == 0 {
return Err(ExplodedDecodeError::InvalidShape);
}
let slot_count = u32::try_from(block_to_statement.len()).map_err(|_| {
ExplodedDecodeError::BlockOutOfBounds {
proc_id: u32::MAX,
block_id: u32::MAX,
slot: u32::MAX,
slot_count: u32::MAX,
}
})?;
let mut mask = vec![
0u32;
crate::dispatch_decode::bitset_word_capacity(
"reachability witness statement mask",
statement_count,
)
.map_err(|_| ExplodedDecodeError::InvalidShape)?
];
for &node in encoded_nodes {
let (proc_id, block_id, fact_id) = decode_node(node);
if fact_filter.is_some_and(|wanted| wanted != fact_id) {
continue;
}
let slot = proc_id
.checked_mul(blocks_per_proc)
.and_then(|base| base.checked_add(block_id))
.ok_or(ExplodedDecodeError::BlockOutOfBounds {
proc_id,
block_id,
slot: u32::MAX,
slot_count,
})?;
let slot_index = crate::dispatch_decode::u32_to_usize(
slot,
"reachability witness block-to-statement slot",
)
.map_err(|_| ExplodedDecodeError::BlockOutOfBounds {
proc_id,
block_id,
slot,
slot_count,
})?;
let Some(&statement) = block_to_statement.get(slot_index) else {
return Err(ExplodedDecodeError::BlockOutOfBounds {
proc_id,
block_id,
slot,
slot_count,
});
};
if statement >= statement_count {
return Err(ExplodedDecodeError::StatementOutOfBounds {
statement,
statement_count,
});
}
try_set_bit(&mut mask, statement).map_err(|_| {
ExplodedDecodeError::StatementOutOfBounds {
statement,
statement_count,
}
})?;
}
Ok(mask)
}