extern crate libc;
mod crunch;
use libc::c_void;
use std::mem;
#[cfg_attr(target_os = "windows", repr(i32))]
#[cfg_attr(target_os = "linux", repr(C))]
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Default)]
pub enum CrnFormat {
FirstValid = -2,
#[default]
Invalid = -1,
Dxt1 = 0,
Dxt3,
Dxt5,
Dxt5cCxY,
Dxt5xGxR,
Dxt5xGBR,
Dxt5Agbr,
DxNXy,
DxNYx,
Dxt5A,
Etc1,
Total,
#[cfg(target_os = "linux")] ForceDWORD = 0xFFFFFFFF,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct LevelInfo {
pub struct_size: u32,
pub width: u32,
pub height: u32,
pub faces: u32,
pub blocks_x: u32,
pub blocks_y: u32,
pub bytes_per_block: u32,
pub format: CrnFormat,
}
impl Default for LevelInfo {
fn default() -> LevelInfo {
LevelInfo {
struct_size: mem::size_of::<LevelInfo>() as u32,
width: 0,
height: 0,
faces: 0,
blocks_x: 0,
blocks_y: 0,
bytes_per_block: 0,
format: CrnFormat::Invalid,
}
}
}
#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct TextureInfo {
pub struct_size: u32,
pub width: u32,
pub height: u32,
pub levels: u32,
pub faces: u32,
pub bytes_per_block: u32,
pub userdata0: u32,
pub userdata1: u32,
pub format: CrnFormat,
}
impl Default for TextureInfo {
fn default() -> TextureInfo {
TextureInfo {
struct_size: mem::size_of::<TextureInfo>() as u32,
width: 0,
height: 0,
levels: 0,
faces: 0,
bytes_per_block: 0,
userdata0: 0,
userdata1: 0,
format: CrnFormat::Invalid,
}
}
}
pub struct CrunchedData<'a> {
pub buffer: &'a [u8],
ctx: *const c_void,
}
impl<'a> CrunchedData<'a> {
pub fn new(buffer: &'a [u8]) -> Self {
CrunchedData {
buffer,
ctx: crunch::unpack_begin(buffer),
}
}
pub fn level_info(&self, level: u32) -> LevelInfo {
crunch::get_level_info(self, level)
}
pub fn texture_info(&self) -> TextureInfo {
crunch::get_texture_info(self)
}
pub fn decode_level(&self, level: u32) -> Option<Vec<u8>> {
let info = self.level_info(level);
let mut dst: Vec<u8> =
vec![0; (info.blocks_x * info.blocks_y * info.bytes_per_block) as usize];
if !crunch::unpack_level(
self.ctx,
&mut dst,
info.blocks_x * info.bytes_per_block,
level,
) {
return None;
}
Some(dst)
}
}
impl Drop for CrunchedData<'_> {
fn drop(&mut self) {
crunch::unpack_end(self.ctx);
}
}
#[cfg(test)]
mod tests;