use adler32::adler32;
use std::fmt::Display;
use std::fs::File;
use std::io;
use std::io::{Read, Write};
#[derive(Debug)]
pub struct Dex {
bytes: Vec<u8>,
}
impl Dex {
pub fn current_checksum(&self) -> [u8; 4] {
self.bytes[8..12]
.try_into()
.expect("Could not convert slice to array!")
}
pub fn expect_checksum(&self) -> [u8; 4] {
let mut hash = adler32(&self.bytes[12..]).expect("Unable to calculate adler32 checksum!");
let mut buffer: [u8; 4] = [0; 4];
for i in (0..4).rev() {
buffer[i] = (hash % 256) as u8;
hash >>= 8;
}
buffer.reverse();
buffer
}
pub fn check_checksum(&self) -> bool {
self.current_checksum() == self.expect_checksum()
}
pub fn correct_checksum(&mut self) -> bool {
let expect = self.expect_checksum();
if self.current_checksum() != expect {
self.bytes[8..12].copy_from_slice(&expect);
true
} else {
false
}
}
pub fn write_to_file(&self, path: &str) -> io::Result<()> {
File::create(path)?.write_all(&self.bytes)
}
}
impl Display for Dex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Dex {{ bytes: {:?} }}", self.bytes)
}
}
impl TryFrom<File> for Dex {
type Error = io::Error;
fn try_from(mut f: File) -> Result<Self, Self::Error> {
let mut bytes = Vec::<u8>::new();
f.read_to_end(&mut bytes).map(|_| Dex { bytes })
}
}
impl TryFrom<String> for Dex {
type Error = io::Error;
fn try_from(path: String) -> Result<Self, Self::Error> {
match File::open(path) {
Ok(f) => Dex::try_from(f),
Err(e) => Err(e),
}
}
}
impl TryFrom<&str> for Dex {
type Error = io::Error;
fn try_from(path: &str) -> Result<Self, Self::Error> {
Dex::try_from(String::from(path))
}
}