use neure::map::from_be_bytes;
use neure::prelude::*;
use std::{cell::RefCell, process::exit};
fn main() -> Result<(), Box<dyn core::error::Error>> {
tracing_subscriber::fmt::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.init();
if let Some(file) = std::env::args().nth(1) {
let head: &[u8] = &[137, 80, 78, 71, 13, 10, 26, 10];
let bytes = std::fs::read(file)?;
let u32_parser = regex::consume(4).try_map(from_be_bytes::<u32>());
let uint8 = regex::consume(1)
.try_map(from_be_bytes::<u8>())
.map(|v| char::from_u32(v as u32).unwrap());
let mut ctx = RegexCtx::new(bytes.as_slice());
if ctx.ctor(&head).is_ok() {
println!("Matching the head, the file seems like a png file");
} else {
println!("Not a png file");
exit(1)
}
for idx in 0.. {
if let Ok(length) = ctx.ctor(&u32_parser) {
let crc_beg = ctx.offset();
let ancillary = ctx.ctor(&uint8)?;
let private = ctx.ctor(&uint8)?;
let reserved = ctx.ctor(&uint8)?;
let safe_copy = ctx.ctor(&uint8)?;
println!(
"In trunk {idx}: ancillary = `{}`, bit 5 = {}: {}",
ancillary,
if ancillary.is_uppercase() { 0 } else { 1 },
if ancillary.is_uppercase() {
"critical"
} else {
"ancillary"
}
);
println!(
"In trunk {idx}: private = `{}`, bit 5 = {}: {}",
private,
if private.is_uppercase() { 0 } else { 1 },
if private.is_uppercase() {
"public"
} else {
"private"
}
);
println!(
"In trunk {idx}: reserved = `{}`, bit 5 = {}",
reserved,
if reserved.is_uppercase() { 0 } else { 1 },
);
println!(
"In trunk {idx}: safe_copy = `{}`, bit 5 = {}: {}",
safe_copy,
if safe_copy.is_uppercase() { 0 } else { 1 },
if safe_copy.is_uppercase() {
"unsafe to copy"
} else {
"safe to copy"
}
);
let data = regex::consume(length as usize);
println!("In trunk {idx}: data length = {length}");
println!("skip data length = {}", ctx.ctor(&data)?.len());
let crc_data = ctx.orig_sub(crc_beg, ctx.offset() - crc_beg)?;
let crc_value = ctx.ctor(&u32_parser)?;
println!(
"Checking the crc value = {}",
crc_value == calc_crc(crc_data)
);
} else {
break;
}
}
}
Ok(())
}
thread_local! {
static CRC_TABLE: RefCell<Option<[u32; 256]>> = const { RefCell::new(None) };
}
pub fn initialize_crc_table() {
CRC_TABLE
.try_with(|table| {
let mut table = table.borrow_mut();
if table.is_none() {
*table = Some({
let mut table: [u32; 256] = [0; 256];
for n in 0..256 {
let mut c = n;
for _ in 0..8 {
if c & 1 == 1 {
c = 0xedb88320u32 ^ (c >> 1);
} else {
c >>= 1;
}
}
table[n as usize] = c;
}
table
})
}
})
.unwrap()
}
pub fn calc_crc(buff: &[u8]) -> u32 {
let mut c = 0xffffffffu32;
initialize_crc_table();
CRC_TABLE
.try_with(|table| {
let table = table.borrow();
if let Some(table) = *table {
for n in 0..buff.len() {
c = table[((c ^ (buff[n] as u32)) & 0xff) as usize] ^ (c >> 8);
}
}
})
.unwrap();
c ^ 0xffffffffu32
}