use crate::Cache;
use std::{ffi::CStr, mem, os::raw::c_char};
#[no_mangle]
pub unsafe extern "C" fn cache_open(path: *const c_char) -> *mut Cache {
let path_cstr = CStr::from_ptr(path);
let path_str = path_cstr.to_str().expect("failed to convert path to str");
let cache = Cache::open(path_str).expect("failed to open cache");
Box::into_raw(Box::new(cache))
}
#[no_mangle]
pub unsafe extern "C" fn cache_read(
cache_ptr: *mut Cache,
archive: u8,
group: u32,
file: u16,
xtea_keys_arg: *const [u32; 4],
out_len: *mut u32,
) -> *mut u8 {
let cache = &mut *cache_ptr;
let mut xtea_keys = None;
if !xtea_keys_arg.is_null() {
xtea_keys = Some(*xtea_keys_arg);
}
let mut buf = cache
.read(archive, group, file, xtea_keys)
.expect("failed reading file");
let data = buf.as_mut_ptr();
*out_len = buf.len() as u32;
mem::forget(buf);
data
}
#[no_mangle]
pub unsafe extern "C" fn cache_read_named_group(
cache_ptr: *mut Cache,
archive: u8,
group: *const c_char,
file: u16,
xtea_keys_arg: *const [u32; 4],
out_len: *mut u32,
) -> *mut u8 {
let cache = &mut *cache_ptr;
let mut xtea_keys = None;
if !xtea_keys_arg.is_null() {
xtea_keys = Some(*xtea_keys_arg);
}
let group_str = CStr::from_ptr(group)
.to_str()
.expect("failed to convert group to str");
let mut buf = cache
.read_named_group(archive, group_str, file, xtea_keys)
.expect("failed reading named group");
let data = buf.as_mut_ptr();
*out_len = buf.len() as u32;
mem::forget(buf);
data
}
#[no_mangle]
pub unsafe extern "C" fn cache_free(buffer: *mut u8) {
if !buffer.is_null() {
drop(Vec::from_raw_parts(buffer, 0, 0))
}
}
#[no_mangle]
pub unsafe extern "C" fn cache_close(cache_ptr: *mut Cache) {
if !cache_ptr.is_null() {
drop(Box::from_raw(cache_ptr))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::{ffi::CString, ptr, slice};
#[test]
fn test_cache_open() {
let cache_str = CString::new("tests/data/cache/cache-read").unwrap();
let cache_ptr = unsafe { cache_open(cache_str.as_ptr()) };
assert!(!cache_ptr.is_null());
}
#[test]
fn test_cache_read() {
let cache_str = CString::new("tests/data/cache/cache-read").unwrap();
let cache_ptr = unsafe { cache_open(cache_str.as_ptr()) };
assert!(!cache_ptr.is_null());
let mut out_len = 0;
let out_len_ptr: *mut u32 = &mut out_len;
let buf = unsafe { cache_read(cache_ptr, 0, 0, 0, ptr::null(), out_len_ptr) };
let buf_data = unsafe { slice::from_raw_parts(buf, out_len as usize) };
assert_eq!("OpenRS2".as_bytes(), buf_data)
}
#[test]
fn test_cache_read_encrypted() {
let cache_str = CString::new("tests/data/cache/cache-read-encrypted").unwrap();
let cache_ptr = unsafe { cache_open(cache_str.as_ptr()) };
assert!(!cache_ptr.is_null());
let mut out_len = 0;
let out_len_ptr: *mut u32 = &mut out_len;
let buf = unsafe { cache_read(cache_ptr, 0, 0, 0, &KEY as *const [u32; 4], out_len_ptr) };
let buf_data = unsafe { slice::from_raw_parts(buf, out_len as usize) };
assert_eq!("OpenRS2".as_bytes(), buf_data)
}
#[test]
fn test_cache_read_named_group() {
let cache_str = CString::new("tests/data/cache/cache-read-named-group").unwrap();
let cache_ptr = unsafe { cache_open(cache_str.as_ptr()) };
assert!(!cache_ptr.is_null());
let mut out_len = 0;
let out_len_ptr: *mut u32 = &mut out_len;
let group_str = CString::new("OpenRS2").unwrap();
let buf = unsafe {
cache_read_named_group(
cache_ptr,
0,
group_str.as_ptr(),
0,
ptr::null(),
out_len_ptr,
)
};
let buf_data = unsafe { slice::from_raw_parts(buf, out_len as usize) };
assert_eq!("OpenRS2".as_bytes(), buf_data)
}
#[test]
fn test_cache_read_named_group_encrypted() {
let cache_str = CString::new("tests/data/cache/cache-read-named-group-encrypted").unwrap();
let cache_ptr = unsafe { cache_open(cache_str.as_ptr()) };
assert!(!cache_ptr.is_null());
let mut out_len = 0;
let out_len_ptr: *mut u32 = &mut out_len;
let group_str = CString::new("OpenRS2").unwrap();
let buf = unsafe {
cache_read_named_group(
cache_ptr,
0,
group_str.as_ptr(),
0,
&KEY as *const [u32; 4],
out_len_ptr,
)
};
let buf_data = unsafe { slice::from_raw_parts(buf, out_len as usize) };
assert_eq!("OpenRS2".as_bytes(), buf_data)
}
const KEY: [u32; 4] = [0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF];
}