HEFGMMUMJ2GGJGF2BEKF7EUL24AO53WJTXKBJSEGT64AV3Y4TBZQC use std::ffi::{CStr, CString};
use std::convert::TryInto;use std::ffi::CStr;use std::hash::Hasher;use std::io::Read;use std::{cmp, fmt, fs, io, marker, mem, ptr, slice, sync};use twox_hash::{xxh3::hash64, XxHash64};const BLOCKSIZELOG_MAX: usize = 17;const BLOCKSIZE_MAX: usize = 1 << BLOCKSIZELOG_MAX;const SEEKABLE_BUFF_SIZE: usize = BLOCKSIZE_MAX;const SEEKABLE_MAXFRAMES: usize = 0x8000000;const MAX_FRAME_DECOMPR_SIZE: u32 = 16;const MAGIC_SKIPPABLE_START: usize = 0x184D2A50;const SKIPPABLE_HEADER_SIZE: usize = 8;const SEEK_TABLE_FOOTER_SIZE: usize = 9;const SEEKABLE_MAGIC_NUMBER: usize = 0x8F92EAB1;const FRAMELOG_STARTING_CAPACITY: usize = 16;
/// The type of seekable compressors.pub struct SeekableCStream {p: *mut ZSTD_seekable_CStream,
#[derive(Clone)]pub struct FrameLogEntry {c_size: u32,d_size: u32,checksum: u64,}/// The type of compressors.pub struct FrameLog {entries: Vec<FrameLogEntry>,checksum_flag: u64,seek_table_pos: u32,seek_table_index: u32,
/// The type of compressors.pub struct FrameLog {p: *mut ZSTD_frameLog,
/// The type of seekable compressors.pub struct SeekableCStream {cstream: CStream,framelog: FrameLog,frame_c_size: u32,frame_d_size: u32,xxh_state: XxHash64,max_frame_size: u32,writing_seek_table: bool,}pub struct SeekEntry {c_offset: usize,d_offset: usize,checksum: u64,
p: *mut ZSTD_seekable,b: *mut R,f: *mut libc::FILE,marker: std::marker::PhantomData<&'a R>,
dstream: *mut ZSTD_DStream,seek_table: SeekTable,src: &'a mut R,decompressed_offset: u64,cur_frame: u32,in_buff: [u8; SEEKABLE_BUFF_SIZE],out_buff: [u8; SEEKABLE_BUFF_SIZE],inn: ZSTD_inBuffer,xxh_state: XxHash64,// marker: marker::PhantomData<&'a R>, //TODO: do we need this marker?
unsafe {if !self.p.is_null() {ZSTD_seekable_free(self.p);self.p = std::ptr::null_mut();}if !self.f.is_null() {fclose(self.f);self.f = std::ptr::null_mut();}if !self.b.is_null() {let b: Box<R> = Box::from_raw(self.b);std::mem::drop(b);self.b = std::ptr::null_mut();
if !self.dstream.is_null() {unsafe {ZSTD_freeDStream(self.dstream);self.dstream = ptr::null_mut();
impl Drop for FrameLog {fn drop(&mut self) {unsafe {if !self.p.is_null() {ZSTD_seekable_freeFrameLog(self.p);self.p = std::ptr::null_mut()}}}}unsafe extern "C" fn zstd_seekable_read<R: std::io::Read + std::io::Seek>(
unsafe extern "C" fn zstd_seekable_read<R: io::Read + io::Seek>(
pub fn new(level: usize, frame_size: usize) -> Result<Self, Error> {unsafe {let p = ZSTD_seekable_createCStream();if p.is_null() {return Err(Error::Null);}let result = ZSTD_seekable_initCStream(p, level as c_int, 1, frame_size as c_uint);if ZSTD_isError(result) != 0 {
pub fn new(level: usize, frame_size: u32) -> Result<Self, Error> {let cstream = unsafe { ZSTD_createCStream() };if cstream.is_null() {return Err(Error::Null);}if frame_size > MAX_FRAME_DECOMPR_SIZE {return Err(Error::Other("FrameParameterUnsupported"));} else {let max_frame_size = if frame_size > 0 {frame_size} else {MAX_FRAME_DECOMPR_SIZE};let result = unsafe { ZSTD_initCStream(cstream, level as c_int) };if unsafe { ZSTD_isError(result) } != 0 {
Ok(SeekableCStream { p })
Ok(SeekableCStream {cstream: CStream { p: cstream },framelog: FrameLog {entries: Vec::with_capacity(FRAMELOG_STARTING_CAPACITY),checksum_flag: 1,seek_table_pos: 0,seek_table_index: 0,},frame_c_size: 0,frame_d_size: 0,xxh_state: XxHash64::with_seed(0),max_frame_size,writing_seek_table: false,})
unsafe {let mut input = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = ZSTD_seekable_compressStream(self.p, &mut output, &mut input);if ZSTD_isError(result) != 0 {return Err(Error::ZSTD(result));
let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let len = cmp::min(input.len() as u32, self.max_frame_size - self.frame_d_size);let mut in_tmp = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};if len > 0 {let ret = unsafe { ZSTD_compressStream(self.cstream.p, &mut output, &mut in_tmp) };if self.framelog.checksum_flag != 0 {self.xxh_state.write(unsafe { slice::from_raw_parts(in_tmp.src as *const _, in_tmp.pos) });}self.frame_c_size += output.pos as u32;self.frame_d_size += in_tmp.pos as u32;if unsafe { ZSTD_isError(ret) } != 0 {return Err(Error::ZSTD(ret));}}if self.max_frame_size == self.frame_d_size {let ret = self.end_stream(&mut output)?;if unsafe { ZSTD_isError(ret) } != 0 {return Err(Error::ZSTD(ret));
Ok((output.pos as usize, input.pos as usize))
}Ok((output.pos as usize, in_tmp.pos as usize))}fn end_frame(&mut self, mut output: ZSTD_outBuffer) -> Result<usize, Error> {let prev_out_pos = output.pos;let ret = unsafe { ZSTD_endStream(self.cstream.p, &mut output) };self.frame_c_size += (output.pos - prev_out_pos) as u32;if ret != 0 {return Ok(ret);}let checksum = if self.framelog.checksum_flag != 0 {self.xxh_state.finish() & 0xFFFFFFFFu64} else {0};self.framelog.log_frame(self.frame_c_size, self.frame_d_size, checksum)?;self.frame_c_size = 0;self.frame_d_size = 0;unsafe { ZSTD_resetCStream(self.cstream.p, 0) };if self.framelog.checksum_flag != 0 {self.xxh_state = XxHash64::with_seed(0);
pub fn end_stream(&mut self, output: &mut [u8]) -> Result<usize, Error> {unsafe {let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = ZSTD_seekable_endStream(self.p, &mut output);if ZSTD_isError(result) != 0 {return Err(Error::ZSTD(result));
pub fn end_stream(&mut self, output: &mut ZSTD_outBuffer) -> Result<usize, Error> {if !self.writing_seek_table && self.frame_d_size != 0 {let end_frame = self.end_frame(*output)?;if unsafe { ZSTD_isError(end_frame) } != 0 {return Err(Error::ZSTD(end_frame));} else if end_frame != 0 {return Ok(end_frame + self.framelog.seek_table_size());
unsafe {let mut input = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = ZSTD_compressStream(self.p, &mut output, &mut input);Ok((output.pos as usize, input.pos as usize, result as usize))}
let mut input = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = unsafe { ZSTD_compressStream(self.p, &mut output, &mut input) };Ok((output.pos as usize, input.pos as usize, result as usize))
unsafe {let mut input = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = ZSTD_compressStream2(self.p, &mut output, &mut input, op as ZSTD_EndDirective);Ok((output.pos as usize, input.pos as usize, result as usize))}
let mut input = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = unsafe {ZSTD_compressStream2(self.p, &mut output, &mut input, op as ZSTD_EndDirective)};Ok((output.pos as usize, input.pos as usize, result as usize))
unsafe {let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = ZSTD_flushStream(self.p, &mut output);Ok((output.pos as usize, result as usize))}
let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = unsafe { ZSTD_flushStream(self.p, &mut output) };Ok((output.pos as usize, result as usize))
unsafe {let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = ZSTD_endStream(self.p, &mut output);if ZSTD_isError(result) != 0 {return Err(Error::ZSTD(result));}Ok(output.pos as usize)
let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let result = unsafe { ZSTD_endStream(self.p, &mut output) };if unsafe { ZSTD_isError(result) } != 0 {return Err(Error::ZSTD(result));
unsafe {let mut input = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,
let mut input = ZSTD_inBuffer {src: input.as_ptr() as *const c_void,size: input.len() as size_t,pos: 0,};let mut output = ZSTD_outBuffer {dst: output.as_mut_ptr() as *mut c_void,size: output.len() as size_t,pos: 0,};let _result = unsafe { ZSTD_decompressStream(self.p, &mut output, &mut input) };Ok((output.pos as usize, input.pos as usize))}}impl<'a, R: io::Read + io::Seek> Seekable<'a, R> {fn make_seekable(source: &'a mut R, dstream: *mut ZSTD_DStream) -> Self {Seekable {dstream,seek_table: SeekTable {entries: Vec::new(),checksum_flag: 1,},src: source,decompressed_offset: 0,cur_frame: 0,in_buff: [0; SEEKABLE_BUFF_SIZE],out_buff: [0; SEEKABLE_BUFF_SIZE],inn: ZSTD_inBuffer {src: ptr::null() as *const c_void,size: 0,
impl<'a> Seekable<'a, ()> {/// Initialise a decompressor with an input buffer.pub fn init_buf(input: &'a [u8]) -> Result<Self, Error> {unsafe {let p = ZSTD_seekable_create();if p.is_null() {return Err(Error::Null);}let result =ZSTD_seekable_initBuff(p, input.as_ptr() as *const c_void, input.len() as size_t);if ZSTD_isError(result) != 0 {return Err(Error::ZSTD(result));}Ok(Seekable {p,f: std::ptr::null_mut(),b: std::ptr::null_mut(),marker: std::marker::PhantomData,})
let mut handle = self.src.take(SEEK_TABLE_FOOTER_SIZE as u64);handle.read(&mut self.in_buff);if slice_to_num(&self.in_buff[5..9])? as usize != SEEKABLE_MAGIC_NUMBER {return Err(Error::Other("PrefixUnknown"));}let checksum_flag = (self.in_buff[4] >> 7) as usize;if ((checksum_flag >> 2) & 0x1f) == 0 {return Err(Error::Other("CorruptionDetected"));
}
let num_frames = slice_to_num(&self.in_buff[..4])? as usize;let size_p_entry: usize = 8 + if checksum_flag != 0 { 4 } else { 0 };let table_size = size_p_entry * num_frames;let frame_size = table_size + SEEK_TABLE_FOOTER_SIZE + SKIPPABLE_HEADER_SIZE;
/// Initialise a decompressor with a file. This method opens the file, and dropping the resulting `Seekable` closes the file.pub fn init_file(name_: &str) -> Result<Self, Error> {unsafe {let name = CString::new(name_).unwrap();let f: *mut libc::FILE = fopen(name.as_ptr(), "rb\0".as_ptr() as *const c_char);if f.is_null() {return Err(Error::CouldNotOpenFile(name_.to_string()));}let p = ZSTD_seekable_create();if p.is_null() {return Err(Error::Null);
let mut remaining = frame_size as usize - SEEK_TABLE_FOOTER_SIZE;let to_read = cmp::min(remaining, SEEKABLE_BUFF_SIZE);self.src.seek(io::SeekFrom::End(-(frame_size as i64)));handle = self.src.take(to_read as u64);handle.read(&mut self.in_buff)?;remaining -= to_read;if slice_to_num(&self.in_buff[..4])? as usize != (MAGIC_SKIPPABLE_START | 0xE) {return Err(Error::Other("PrefixUnknown"));}if slice_to_num(&self.in_buff[4..8])? as usize + SKIPPABLE_HEADER_SIZE != frame_size {return Err(Error::Other("PrefixUnknown"));}let mut entries: Vec<SeekEntry> = Vec::with_capacity((num_frames + 1) as usize);let (mut idx, mut pos) = (0usize, 8usize);let (mut c_offset, mut d_offset) = (0, 0);let buffer_ptr = (&mut self.in_buff).as_mut_ptr();while idx < num_frames {if pos + size_p_entry > SEEKABLE_BUFF_SIZE {let offset = SEEKABLE_BUFF_SIZE;let to_read = cmp::min(remaining, SEEKABLE_BUFF_SIZE - offset);// FIXME: replace this pointer arithmetic with something saferunsafe { (buffer_ptr.add(pos)).copy_to(buffer_ptr, offset) };handle = self.src.take(to_read as u64);// FIXME: if pointer arithmetic replace, this needs to changehandle.read(unsafe { slice::from_raw_parts_mut(buffer_ptr.add(offset), to_read) })?;remaining -= to_read;pos = 0;
let result = ZSTD_seekable_initFile(p, f as *mut FILE);if ZSTD_isError(result) != 0 {return Err(Error::ZSTD(result));
entries[idx].c_offset = c_offset;entries[idx].d_offset = d_offset;c_offset += slice_to_num(&self.in_buff[pos..pos + 4])? as usize;pos += 4;d_offset += slice_to_num(&self.in_buff[pos..pos + 4])? as usize;pos += 4;if checksum_flag != 0 {entries[idx].checksum = slice_to_num(&self.in_buff[pos..pos + 4])? as u64;pos += 4;
impl<'a, R: std::io::Read + std::io::Seek> Seekable<'a, R> {/// Initialise a decompressor with a file. This method opens the file, and dropping the resulting `Seekable` closes the file.pub fn init(r: Box<R>) -> Result<Self, Error> {unsafe {let p = ZSTD_seekable_create();if p.is_null() {return Err(Error::Null);}let opaque = Box::into_raw(r) as *mut R;let adv = ZSTD_seekable_customFile {opaque: opaque as *mut c_void,read: Some(zstd_seekable_read::<R>),seek: Some(zstd_seekable_seek::<R>),};let result = ZSTD_seekable_initAdvanced(p, adv);if ZSTD_isError(result) != 0 {return Err(Error::ZSTD(result));}Ok(Seekable {p,f: std::ptr::null_mut(),b: opaque,marker: std::marker::PhantomData,})
fn init_advanced(&mut self) -> Result<(), Error> {self.load_seek_table()?;self.decompressed_offset = u64::MAX;self.cur_frame = u32::MAX;let dstream_init = unsafe { ZSTD_initDStream(self.dstream) };if unsafe { ZSTD_isError(dstream_init) } != 0 {Err(Error::ZSTD(dstream_init))} else {Ok(())
pub fn into_inner(self) -> Box<R> {unsafe { Box::from_raw(self.b) }
/// Decompress a single frame. This method internally calls `decompress`, and `dest` must be exactly the size of the uncompressed frame.pub fn decompress_frame(&mut self, dest: &mut [u8], index: usize) -> Result<usize, Error> {let dec_size = self.get_frame_decompressed_size(index)?;if dest.len() < dec_size {return Err(Error::Other("DestinationSizeTooSmall"));}self.decompress(dest,dec_size,self.seek_table.entries[index].d_offset as u64,)
pub fn decompress(&mut self, out: &mut [u8], offset: u64) -> Result<usize, Error> {unsafe {let result = ZSTD_seekable_decompress(self.p,out.as_mut_ptr() as *mut c_void,out.len() as size_t,offset,);if ZSTD_isError(result) != 0 {return Err(Error::ZSTD(result));
pub fn decompress(&mut self,out: &mut [u8],len: usize,offset: u64,) -> Result<usize, Error> {let mut tgt_frame = self.seekable_offset_to_frame_index(offset);let dst = out.as_mut_ptr();loop {if tgt_frame as usize != self.cur_frame as usize || offset != self.decompressed_offset {self.decompressed_offset = self.seek_table.entries[tgt_frame].d_offset as u64;self.cur_frame = tgt_frame as u32;self.src.seek(io::SeekFrom::Start(self.seek_table.entries[tgt_frame].c_offset as u64,));self.inn = ZSTD_inBuffer {src: self.in_buff.as_ptr() as *const _ as *const c_void,size: 0,pos: 0,};self.xxh_state = XxHash64::with_seed(0);unsafe { ZSTD_resetDStream(self.dstream) };
Ok(result as usize)
while self.decompressed_offset < offset + len as u64 {let mut out_tmp = if self.decompressed_offset < offset {ZSTD_outBuffer {dst: self.out_buff.as_mut_ptr() as *mut c_void,size: cmp::min(SEEKABLE_BUFF_SIZE,(offset - self.decompressed_offset) as size_t,),pos: 0,}} else {ZSTD_outBuffer {dst: dst as *mut c_void,size: len,pos: (self.decompressed_offset - offset) as size_t,}};let prev_out_pos = out_tmp.pos;let mut to_read =unsafe { ZSTD_decompressStream(self.dstream, &mut out_tmp, &mut self.inn) };if unsafe { ZSTD_isError(to_read) } != 0 {return Err(Error::ZSTD(to_read));}if self.seek_table.checksum_flag != 0 {// FIXME: replace this pointer arithmetic with something saferlet tmp: &[u8] = unsafe {slice::from_raw_parts_mut((out_tmp.dst as *mut u8).add(prev_out_pos),out_tmp.pos - prev_out_pos,)};self.xxh_state.write(tmp)}self.decompressed_offset += (out_tmp.pos - prev_out_pos) as u64;if to_read == 0 {if self.seek_table.checksum_flag != 0&& (self.xxh_state.finish() & 0xFFFFFFFFu64)!= self.seek_table.entries[tgt_frame].checksum{return Err(Error::Other("CorruptionDetected"));}if self.decompressed_offset < offset + len as u64 {tgt_frame = self.seekable_offset_to_frame_index(self.decompressed_offset);}break;}if self.inn.pos == self.inn.size {to_read = cmp::min(to_read, SEEKABLE_BUFF_SIZE);let mut handle = self.src.take(to_read as u64);handle.read(&mut self.in_buff).map_err(|_| Error::Other("Not able to read buffer"));self.inn.size = to_read;self.inn.pos = 0;}}if self.decompressed_offset != offset + len as u64 {break;}}Ok(len)}}impl<'a> Seekable<'a, io::Cursor<&'a mut [u8]>> {/// Initialise a decompressor with an input buffer.pub fn init_buf(input: &'a mut [u8]) -> Result<Self, Error> {let dstream = unsafe { ZSTD_createDStream() };if dstream.is_null() {return Err(Error::Null);
let mut source = io::Cursor::new(input);let mut seekable = Seekable::make_seekable(&mut source, dstream);seekable.init_advanced()?;Ok(seekable)}}impl<'a> Seekable<'a, fs::File> {/// Initialise a decompressor with a file. This method opens the file, and dropping the resulting `Seekable` closes the file.pub fn init_file(name: &'a str) -> Result<Self, Error> {let mut source = fs::File::create(name)?;let mut seekable = Seekable::make_seekable(&mut source, ptr::null_mut());seekable.init_advanced()?;Ok(seekable)}}impl<'a, R: io::Read + io::Seek> Seekable<'a, Box<R>> {/// Initialise a decompressor with a file. This method opens the file, and dropping the resulting `Seekable` closes the file.pub fn init(source: &'a mut Box<R>) -> Result<Self, Error> {let source = &mut *source;let mut seekable = Seekable::make_seekable(source, ptr::null_mut());seekable.init_advanced()?;Ok(seekable)
pub fn get_frame_compressed_offset(&self, frame_index: usize) -> c_ulonglong {unsafe { ZSTD_seekable_getFrameCompressedOffset(self.p, frame_index as c_uint) }
pub fn get_frame_compressed_offset(&self, frame_index: usize) -> Result<usize, Error> {if frame_index >= self.get_num_frames() {Err(Error::Other("FrameIndexTooLarge"))} else {Ok(self.seek_table.entries[frame_index].c_offset)}
pub fn get_frame_compressed_size(&self, frame_index: usize) -> usize {unsafe { ZSTD_seekable_getFrameCompressedSize(self.p, frame_index as c_uint) as usize }
pub fn get_frame_compressed_size(&self, frame_index: usize) -> Result<usize, Error> {if frame_index >= self.get_num_frames() {Err(Error::Other("FrameIndexTooLarge"))} else {Ok(self.seek_table.entries[frame_index + 1].c_offset- self.seek_table.entries[frame_index].c_offset)}
pub fn get_frame_decompressed_offset(&self, frame_index: usize) -> u64 {unsafe { ZSTD_seekable_getFrameDecompressedOffset(self.p, frame_index as c_uint) }
pub fn get_frame_decompressed_offset(&self, frame_index: usize) -> Result<usize, Error> {if frame_index >= self.get_num_frames() {Err(Error::Other("FrameIndexTooLarge"))} else {Ok(self.seek_table.entries[frame_index].d_offset)}
pub fn get_frame_decompressed_size(&self, frame_index: usize) -> usize {unsafe { ZSTD_seekable_getFrameDecompressedSize(self.p, frame_index as c_uint) as usize }}/// Decompress a single frame. This method internally calls `decompress`, and `dest` must be exactly the size of the uncompressed frame.pub fn decompress_frame(&mut self, dest: &mut [u8], index: usize) -> usize {unsafe {ZSTD_seekable_decompressFrame(self.p,dest.as_mut_ptr() as *mut c_void,dest.len() as size_t,index as c_uint,) as usize
pub fn get_frame_decompressed_size(&self, frame_index: usize) -> Result<usize, Error> {if frame_index > self.get_num_frames() {Err(Error::Other("FrameIndexTooLarge"))} else {Ok(self.seek_table.entries[frame_index + 1].d_offset- self.seek_table.entries[frame_index].d_offset)
pub fn seekable_offset_to_frame_index(&mut self, offset: u64) -> usize {unsafe { ZSTD_seekable_offsetToFrameIndex(self.p, offset) as usize }
pub fn seekable_offset_to_frame_index(&self, offset: u64) -> usize {if offset >= self.seek_table.entries[self.get_num_frames()].d_offset as u64 {return self.get_num_frames();}let (mut lo, mut hi) = (0, self.get_num_frames());while lo + 1 < hi {let mid = lo + ((hi - lo) >> 1);if self.seek_table.entries[mid].d_offset as u64 <= offset {lo = mid} else {hi = mid;}}lo
impl Dst for [u8; 512] {fn as_mut_ptr(&mut self) -> *mut u8 {self.as_mut().as_mut_ptr()}fn as_slice(&self) -> &[u8] {self.as_ref()}fn len(&self) -> usize {512}fn new() -> Self {unsafe { std::mem::MaybeUninit::uninit().assume_init() }}}impl Dst for [u8; 1024] {fn as_mut_ptr(&mut self) -> *mut u8 {self.as_mut().as_mut_ptr()}fn as_slice(&self) -> &[u8] {self.as_ref()}fn len(&self) -> usize {1024}fn new() -> Self {unsafe { std::mem::MaybeUninit::uninit().assume_init() }}}impl Dst for [u8; 2048] {fn as_mut_ptr(&mut self) -> *mut u8 {self.as_mut().as_mut_ptr()}fn as_slice(&self) -> &[u8] {self.as_ref()}fn len(&self) -> usize {2048}fn new() -> Self {unsafe { std::mem::MaybeUninit::uninit().assume_init() }}}impl Dst for [u8; 4096] {fn as_mut_ptr(&mut self) -> *mut u8 {self.as_mut().as_mut_ptr()}fn as_slice(&self) -> &[u8] {self.as_ref()}fn len(&self) -> usize {4096}fn new() -> Self {unsafe { std::mem::MaybeUninit::uninit().assume_init() }}}
fn compress_frame<D: Dst>(src_ptr: *const u8,src_len: size_t,level: usize,) -> Result<CompressedFrame<D>, Error> {unsafe {let mut dst = D::new();let checksum = xxh64(src_ptr, src_len as c_int);let ret = ZSTD_compress(
let ret = unsafe {ZSTD_compress(
let p = unsafe { ZSTD_seekable_createFrameLog(1) };assert!(!p.is_null());FrameLog { p }
FrameLog {entries: Vec::new(),checksum_flag: 1,seek_table_pos: 0,seek_table_index: 0,}}pub fn log_frame(&mut self, c_size: u32, d_size: u32, checksum: u64) -> Result<(), Error> {if self.entries.len() == SEEKABLE_MAXFRAMES {return Err(Error::Other("FrameIndexTooLarge"));}self.entries.push(FrameLogEntry {c_size,d_size,checksum,});Ok(())}#[inline(always)]pub fn seek_table_size(&self) -> usize {let size_p_frame = 8 + if self.checksum_flag != 0 { 4 } else { 0 };return SKIPPABLE_HEADER_SIZE + size_p_frame * self.entries.len() + SEEK_TABLE_FOOTER_SIZE;
pub fn log_frame<D: Dst>(&mut self, frame: &CompressedFrame<D>) -> usize {unsafe {ZSTD_seekable_logFrame(self.p,frame.dst_size as c_uint,frame.src_size as c_uint,frame.checksum,) as usize
// FIXME: replace this pointer arithmetic with something saferunsafe {ptr::copy_nonoverlapping(tmp.as_ptr().add(self.seek_table_pos as usize - offset) as *const usize,output.dst.add(output.pos) as *mut usize,len_write,)};output.pos += len_write;return if len_write < 4 {self.seek_table_size() - self.seek_table_pos as usize} else {0};
}
pub fn write_seek_table(&mut self, output: &mut ZSTD_outBuffer) -> Result<usize, Error> {let size_p_frame = 8 + if self.checksum_flag != 0 { 4 } else { 0 };let table_len = self.seek_table_size();let mut ret: usize = self.stwrite32(output, MAGIC_SKIPPABLE_START | 0xE, 0);if ret != 0 {return Ok(ret);};// assert!(table_len <= usize::MAX);ret = self.stwrite32(output, table_len - SKIPPABLE_HEADER_SIZE, 4);if ret != 0 {return Ok(ret);};let mut i = self.seek_table_index as usize;while i < self.entries.len() {let start = SKIPPABLE_HEADER_SIZE + size_p_frame * i;// assert!(start + 8 <= usize::MAX);ret = self.stwrite32(output, self.entries[i].c_size as usize, start);if ret != 0 {return Ok(ret);};ret = self.stwrite32(output, self.entries[i].d_size as usize, start + 4);if ret != 0 {return Ok(ret);};if self.checksum_flag != 0 {ret = self.stwrite32(output, self.entries[i].checksum as usize, start + 8);if ret != 0 {return Ok(ret);};}
pub fn parallel_compress<W: std::io::Write, D: Dst + 'static>(src: &[u8],
ret = self.stwrite32(output,self.entries.len(),table_len - SEEK_TABLE_FOOTER_SIZE,);if ret != 0 {return Ok(ret);};if output.size - output.pos < 1 {return Ok(table_len - self.seek_table_pos as usize);}if (self.seek_table_pos as usize) < table_len {let sfd = (self.checksum_flag << 7) as u8;let array = unsafe { slice::from_raw_parts_mut(output.dst as *mut u8, output.size) };array.get_mut(output.pos).and_then(|el| Some(*el = sfd)).ok_or(Error::Other("index out of bounds"));output.pos += 1;}ret = self.stwrite32(output, SEEKABLE_MAGIC_NUMBER, table_len - 4);if ret != 0 {return Ok(ret);};if self.seek_table_pos as usize != table_len {Err(Error::Other("Generic error from ZSTD"))} else {Ok(0)}}}pub fn parallel_compress<W: io::Write, D: Dst + 'static>(src: &'static [u8],
let frames: Vec<CompressedFrame<D>> = unsafe {let mut frames = Vec::with_capacity(n);frames.set_len(n);for (i, frame) in rx.iter().take(n) {frames[i] = frame}frames};
let mut frames: Vec<CompressedFrame<D>> = Vec::with_capacity(n);unsafe { frames.set_len(n) };for (i, frame) in rx.iter().take(n) {frames[i] = frame?;}
use libc::{c_void, size_t, c_int, c_uint, c_char, c_ulonglong};#[repr(C)]#[derive(Debug, Copy, Clone)]pub struct ZSTD_seekable_CStream {_unused: [u8; 0],}
use libc::{c_char, c_int, c_longlong, c_uint, c_void, size_t};
}pub type ZSTD_seekable_read = ::std::option::Option<unsafe extern "C" fn(opaque: *mut ::std::os::raw::c_void,buffer: *mut ::std::os::raw::c_void,n: size_t,) -> ::std::os::raw::c_int,>;pub type ZSTD_seekable_seek = ::std::option::Option<unsafe extern "C" fn(opaque: *mut ::std::os::raw::c_void,offset: ::std::os::raw::c_longlong,origin: ::std::os::raw::c_int,) -> ::std::os::raw::c_int,>;#[repr(C)]#[derive(Debug, Copy, Clone)]pub struct ZSTD_seekable_customFile {pub opaque: *mut ::std::os::raw::c_void,pub read: ZSTD_seekable_read,pub seek: ZSTD_seekable_seek,
pub fn ZSTD_seekable_createCStream() -> *mut ZSTD_seekable_CStream;pub fn ZSTD_seekable_freeCStream(zcs: *mut ZSTD_seekable_CStream) -> size_t;pub fn ZSTD_seekable_initCStream(zcs: *mut ZSTD_seekable_CStream,compressionLevel: c_int,checksumFlag: c_int,maxFrameSize: c_uint,) -> size_t;pub fn ZSTD_seekable_compressStream(zcs: *mut ZSTD_seekable_CStream,output: *mut ZSTD_outBuffer,input: *mut ZSTD_inBuffer,) -> size_t;pub fn ZSTD_seekable_endStream(zcs: *mut ZSTD_seekable_CStream,output: *mut ZSTD_outBuffer,) -> size_t;pub fn ZSTD_seekable_createFrameLog(checksumFlag: c_int) -> *mut ZSTD_frameLog;pub fn ZSTD_seekable_freeFrameLog(fl: *mut ZSTD_frameLog) -> size_t;pub fn ZSTD_seekable_logFrame(fl: *mut ZSTD_frameLog,compressedSize: c_uint,decompressedSize: c_uint,checksum: c_uint,) -> size_t;pub fn ZSTD_seekable_writeSeekTable(fl: *mut ZSTD_frameLog,output: *mut ZSTD_outBuffer,) -> size_t;pub fn ZSTD_seekable_create() -> *mut ZSTD_seekable;pub fn ZSTD_seekable_free(zs: *mut ZSTD_seekable) -> size_t;pub fn ZSTD_seekable_initBuff(zs: *mut ZSTD_seekable,src: *const c_void,srcSize: size_t,) -> size_t;pub fn ZSTD_seekable_initFile(zs: *mut ZSTD_seekable, src: *mut libc::FILE) -> size_t;pub fn ZSTD_seekable_decompress(zs: *mut ZSTD_seekable,dst: *mut c_void,dstSize: size_t,offset: c_ulonglong,) -> size_t;pub fn ZSTD_seekable_decompressFrame(zs: *mut ZSTD_seekable,dst: *mut c_void,dstSize: size_t,frameIndex: c_uint,) -> size_t;pub fn ZSTD_seekable_getNumFrames(zs: *mut ZSTD_seekable) -> c_uint;pub fn ZSTD_seekable_getFrameCompressedOffset(zs: *mut ZSTD_seekable,frameIndex: c_uint,) -> c_ulonglong;pub fn ZSTD_seekable_getFrameDecompressedOffset(zs: *mut ZSTD_seekable,frameIndex: c_uint,) -> c_ulonglong;pub fn ZSTD_seekable_getFrameCompressedSize(zs: *mut ZSTD_seekable,frameIndex: c_uint,) -> size_t;pub fn ZSTD_seekable_getFrameDecompressedSize(zs: *mut ZSTD_seekable,frameIndex: c_uint,) -> size_t;pub fn ZSTD_seekable_offsetToFrameIndex(zs: *mut ZSTD_seekable,offset: c_ulonglong,) -> c_uint;
pub fn ZSTD_seekable_initAdvanced(zs: *mut ZSTD_seekable,src: ZSTD_seekable_customFile,) -> size_t;pub fn ZSTD_initCStream(zcs: *mut ZSTD_CStream,compressionLevel: c_int,) -> size_t;
pub fn ZSTD_initCStream(zcs: *mut ZSTD_CStream, compressionLevel: c_int) -> size_t;
"src/bindings.rs","xxh64.c","zstd/contrib/seekable_format/zstd_seekable.h","zstd/contrib/seekable_format/zstdseek_compress.c","zstd/contrib/seekable_format/zstdseek_decompress.c","zstd/lib/common/mem.h","zstd/lib/common/xxhash.h","zstd/lib/zstd.h","zstd/lib/common/zstd_errors.h",
"src/bindings.rs"