#[cfg(test)]
mod properties;
pub mod utils;
mod seeds;
#[cfg(test)]
pub use properties::is_random;
pub use seeds::RANDOM_TABLES;
#[derive(PartialEq, Debug, Clone, Default)]
pub struct Table(pub Vec<u8>);
pub fn apply(table: &Table, n: u8) -> u8 {
table.0[n as usize]
}
pub fn inverse_table(table: &Table) -> Table {
let mut result = vec![0;256];
for (i, c) in table.0.iter().enumerate() {
result[*c as usize] = i as u8;
}
Table(result)
}
pub fn compose_table(f: &Table, g: &Table) -> Table {
Table((0..256).map(|i| f.0[g.0[i] as usize]).collect())
}
pub fn decompose_table(h: &Table, f: &Table) -> Table {
compose_table(&inverse_table(f), h)
}
#[cfg(test)]
pub fn random_table() -> Table {
let mut result = Vec::with_capacity(256);
let mut unused = (0..=255).collect::<Vec<u8>>();
for _ in 0..256 {
result.push(unused.swap_remove(rand::random::<usize>() % unused.len()));
}
if !is_random(&result) {
random_table()
}
else {
Table(result)
}
}
#[cfg(test)]
pub fn many_tables() -> Vec<Table> {
let unrandom = vec![
id_table(),
shifted_table(1),
shifted_table(2),
shifted_table(3),
symmetric_table()
];
let random = (0..24).map(|_| random_table()).collect::<Vec<Table>>();
vec![random, unrandom].concat()
}
#[cfg(test)]
pub fn id_table() -> Table {
Table((0..=255).collect())
}
#[cfg(test)]
fn shifted_table(n: usize) -> Table {
Table((0..256).map(|i| ((i + n) % 256) as u8).collect())
}
#[cfg(test)]
fn symmetric_table() -> Table {
Table((0..=255).map(|i| 255 - i).collect())
}