1
Fork 0
mirror of https://github.com/redstrate/Physis.git synced 2025-07-03 09:17:45 +00:00
physis/src/crc.rs
Joshua Goins e751ffa765 Update dependencies, remove bitrotten code, update docs
I updated our dependencies like binrw to 0.15, which is pretty nice as
that means we no longer depend on Syn 1.x. I also finally upgraded to
bitflags 2.x, which doesn't really mean anything except we're on
better supported version.

Additionally, I removed some bitrotten code that no longer compiles.
This was mostly benchmark stuff, but since I don't actively keep track
of that I felt it was better to remove it. I can always add it back once
I'm ready to tackle that again.
2025-05-09 15:16:23 -04:00

138 lines
3.2 KiB
Rust

// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later
use libz_rs_sys::z_off_t;
use std::ops::{Add, AddAssign, BitXor, BitXorAssign};
/// CRC used for filepath hashes in index file
pub(crate) struct Jamcrc {
table: [u32; 256],
}
impl Jamcrc {
pub(crate) const fn new() -> Self {
let mut table: [u32; 256] = [0u32; 256];
let polynomial: u32 = 0xEDB88320;
let mut i = 0;
while i < table.len() {
let mut c: u32 = i as u32;
let mut j = 0;
while j < 8 {
if (c & 1u32) == 1u32 {
c = polynomial ^ (c >> 1);
} else {
c >>= 1;
}
j += 1;
}
table[i] = c;
i += 1;
}
Self { table }
}
pub(crate) fn checksum(&self, bytes: &[u8]) -> u32 {
let mut c: u32 = 0xFFFFFFFF;
for byte in bytes {
c = self.table[((c ^ *byte as u32) & 0xFF) as usize] ^ (c >> 8);
}
!(c ^ 0xFFFFFFFF)
}
}
fn crc32(crc: u32, s: &[u8]) -> u32 {
unsafe { libz_rs_sys::crc32(crc.into(), s.as_ptr(), s.len() as u32) as u32 }
}
fn crc32_combine(crc1: u32, crc2: u32, len2: usize) -> u32 {
libz_rs_sys::crc32_combine(crc1.into(), crc2.into(), len2 as z_off_t) as u32
}
/// CRC used for shader keys
/// Credit to https://github.com/NotNite/crcracker/ for the original Rust code
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
pub(crate) struct XivCrc32 {
pub crc: u32,
pub len: usize,
}
impl XivCrc32 {
pub(crate) fn new(crc: u32, len: usize) -> Self {
Self { crc, len }
}
}
impl From<&[u8]> for XivCrc32 {
fn from(s: &[u8]) -> Self {
Self::new(!crc32(0xFFFFFFFF, s), s.len())
}
}
impl<const N: usize> From<&[u8; N]> for XivCrc32 {
fn from(s: &[u8; N]) -> Self {
Self::new(!crc32(0xFFFFFFFF, s), N)
}
}
impl From<&str> for XivCrc32 {
fn from(s: &str) -> Self {
Self::from(s.as_bytes())
}
}
impl Add<XivCrc32> for XivCrc32 {
type Output = XivCrc32;
fn add(self, rhs: XivCrc32) -> Self::Output {
Self::new(
crc32_combine(self.crc, rhs.crc, rhs.len),
self.len + rhs.len,
)
}
}
impl AddAssign<XivCrc32> for XivCrc32 {
fn add_assign(&mut self, rhs: XivCrc32) {
self.crc = crc32_combine(self.crc, rhs.crc, rhs.len);
self.len += rhs.len;
}
}
impl BitXor<XivCrc32> for XivCrc32 {
type Output = XivCrc32;
fn bitxor(self, rhs: XivCrc32) -> Self::Output {
Self::new(self.crc ^ rhs.crc, self.len.max(rhs.len))
}
}
impl BitXorAssign<XivCrc32> for XivCrc32 {
fn bitxor_assign(&mut self, rhs: XivCrc32) {
self.crc ^= rhs.crc;
self.len = self.len.max(rhs.len);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_jamcrc() {
const CRC: Jamcrc = Jamcrc::new();
let bytes: [u8; 9] = [1, 1, 2, 4, 5, 6, 12, 12, 12];
assert_eq!(2411431516, CRC.checksum(&bytes))
}
#[test]
fn check_xivcrc() {
let str = "Default";
assert_eq!(XivCrc32::from(str).crc, 2978997821);
}
}