v86/src/rust/zstd.rs
2020-12-31 19:14:33 -06:00

106 lines
2.7 KiB
Rust

use std::alloc;
extern "C" {
fn ZSTD_createDStream() -> u32;
fn ZSTD_freeDStream(ctx: u32) -> i32;
fn ZSTD_decompressStream_simpleArgs(
ctx: u32,
dst: *mut u8,
dstCapacity: u32,
dstPos: *mut u32,
src: *const u8,
srcSize: u32,
srcPos: *mut u32,
) -> i32;
fn ZSTD_isError(err: i32) -> bool;
}
const MALLOC_ALIGN: usize = 16;
// malloc and free are needed by the zstd library
#[no_mangle]
pub unsafe fn v86_malloc(size: u32) -> u32 {
let layout = alloc::Layout::from_size_align(size as usize + 4, MALLOC_ALIGN).unwrap();
let addr = alloc::alloc(layout);
*(addr as *mut u32) = size as u32;
addr as u32 + 4
}
#[no_mangle]
pub unsafe fn v86_free(addr: u32) {
let size = *((addr - 4) as *mut u32);
let layout = alloc::Layout::from_size_align(size as usize + 4, MALLOC_ALIGN).unwrap();
alloc::dealloc((addr - 4) as *mut u8, layout)
}
pub struct ZstdContext {
ctx: u32,
src: *mut u8,
src_size: u32,
src_pos: u32,
}
#[no_mangle]
pub unsafe fn zstd_create_ctx(src_size: u32) -> *mut ZstdContext {
let src = alloc::alloc(alloc::Layout::from_size_align(src_size as usize, 1).unwrap());
let ctx = ZSTD_createDStream();
let result = alloc::alloc(alloc::Layout::new::<ZstdContext>()) as *mut ZstdContext;
*result = ZstdContext {
ctx,
src,
src_size,
src_pos: 0,
};
result
}
#[no_mangle]
pub unsafe fn zstd_get_src_ptr(ctx: *mut ZstdContext) -> *mut u8 { (*ctx).src }
#[no_mangle]
pub unsafe fn zstd_free_ctx(ctx: *mut ZstdContext) {
alloc::dealloc(
(*ctx).src,
alloc::Layout::from_size_align((*ctx).src_size as usize, 1).unwrap(),
);
ZSTD_freeDStream((*ctx).ctx);
std::ptr::drop_in_place(ctx);
}
#[no_mangle]
pub unsafe fn zstd_read(ctx: *mut ZstdContext, length: u32) -> *mut u8 {
let dst = alloc::alloc(alloc::Layout::from_size_align(length as usize, 1).unwrap());
let mut dst_pos = 0;
let result = ZSTD_decompressStream_simpleArgs(
(*ctx).ctx,
dst,
length,
&mut dst_pos,
(*ctx).src,
(*ctx).src_size,
&mut (*ctx).src_pos,
);
if ZSTD_isError(result) {
dbg_log!(
"ZSTD_decompressStream_simpleArgs returned error: {}",
result
);
dbg_assert!(false);
zstd_read_free(dst, length);
return std::ptr::null_mut::<u8>();
}
if dst_pos != length {
dbg_assert!(false, "ZSTD: Partial read");
zstd_read_free(dst, length);
return std::ptr::null_mut::<u8>();
}
dst
}
#[no_mangle]
pub unsafe fn zstd_read_free(ptr: *mut u8, length: u32) {
alloc::dealloc(
ptr,
alloc::Layout::from_size_align(length as usize, 1).unwrap(),
);
}