pub fn inverse_bwt(tt: &mut [u32], orig_ptr: usize, mut c: [u32; 256]) -> Option<u32> {
let n = tt.len();
let mut sum = 0u32;
for ci in c.iter_mut() {
let count = *ci;
*ci = sum;
sum += count;
}
if sum as usize != n || orig_ptr >= n {
return None;
}
for i in 0..n {
let b = (tt[i] & 0xFF) as usize;
let idx = c[b] as usize;
if idx >= n {
return None; }
tt[idx] |= (i as u32) << 8;
c[b] += 1;
}
Some(tt[orig_ptr] >> 8)
}
#[inline]
pub fn next_byte(tt: &[u32], t_pos: &mut u32) -> u8 {
*t_pos = tt[*t_pos as usize];
let b = *t_pos as u8;
*t_pos >>= 8;
b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple_inverse() {
let mut tt: Vec<u32> = vec![1, 0, 2, 1, 0, 0];
let mut c = [0u32; 256];
for &b in &tt {
c[b as usize] += 1;
}
let mut t_pos = inverse_bwt(&mut tt, 3, c).expect("consistent counts decode");
let mut output = Vec::new();
for _ in 0..6 {
output.push(next_byte(&tt, &mut t_pos));
}
assert_eq!(output.len(), 6);
}
#[test]
fn inconsistent_counts_rejected_not_ub() {
let mut tt: Vec<u32> = vec![1, 0, 2, 1, 0, 0]; let mut c = [0u32; 256];
c[0] = 2; c[1] = 1; c[2] = 1;
assert!(inverse_bwt(&mut tt, 3, c).is_none());
}
}