#![doc(html_root_url = "https://docs.rs/xz/0.4.6")]
#![deny(missing_docs)]
#[cfg(any(
all(feature = "xz-core", feature = "xz-sys"),
all(feature = "xz-core", feature = "liblzma-sys"),
all(feature = "xz-sys", feature = "liblzma-sys"),
))]
compile_error!("Enable exactly one of `xz-core`, `xz-sys`, or `liblzma-sys`");
#[cfg(not(any(feature = "xz-core", feature = "xz-sys", feature = "liblzma-sys")))]
compile_error!("Enable `xz-core`, `xz-sys`, or `liblzma-sys`");
#[cfg(feature = "xz-core")]
pub(crate) mod sys {
pub(crate) use xz_core::check::check::lzma_check_is_supported;
pub(crate) use xz_core::common::{
alone_decoder::lzma_alone_decoder,
alone_encoder::lzma_alone_encoder,
auto_decoder::lzma_auto_decoder,
common::{lzma_code, lzma_end, lzma_memlimit_get, lzma_memlimit_set},
easy_encoder::lzma_easy_encoder,
filter_decoder::{lzma_properties_decode, lzma_raw_decoder},
filter_encoder::lzma_raw_encoder,
index::{lzma_index_end, lzma_index_uncompressed_size},
index_decoder::lzma_index_buffer_decode,
lzip_decoder::lzma_lzip_decoder,
stream_decoder::lzma_stream_decoder,
stream_encoder::lzma_stream_encoder,
stream_flags_decoder::lzma_stream_footer_decode,
string_conversion::LZMA_PRESET_DEFAULT,
};
#[cfg(feature = "parallel")]
pub(crate) use xz_core::common::{
filter_encoder::lzma_mt_block_size,
stream_mt::{
lzma_stream_decoder_mt, lzma_stream_encoder_mt, lzma_stream_encoder_mt_memusage,
},
};
pub(crate) use xz_core::lz::lz_encoder::lzma_mf_is_supported;
pub(crate) use xz_core::lzma::lzma_encoder_presets::{
lzma_lzma_preset, LZMA_PRESET_LEVEL_MASK,
};
pub(crate) use xz_core::types::*;
}
#[cfg(feature = "xz-sys")]
pub(crate) mod sys {
pub(crate) use xz_sys::*;
}
#[cfg(feature = "liblzma-sys")]
pub(crate) mod sys {
pub(crate) use liblzma_sys::*;
}
use crate::sys as liblzma_sys;
use std::io::{self, prelude::*};
pub mod stream;
pub mod bufread;
pub mod read;
pub mod write;
pub fn decode_all<R: Read>(source: R) -> io::Result<Vec<u8>> {
let mut vec = Vec::new();
let mut r = read::XzDecoder::new(source);
r.read_to_end(&mut vec)?;
Ok(vec)
}
pub fn encode_all<R: Read>(source: R, level: u32) -> io::Result<Vec<u8>> {
let mut vec = Vec::new();
let mut r = read::XzEncoder::new(source, level);
r.read_to_end(&mut vec)?;
Ok(vec)
}
pub fn copy_encode<R: Read, W: Write>(source: R, mut destination: W, level: u32) -> io::Result<()> {
io::copy(&mut read::XzEncoder::new(source, level), &mut destination)?;
Ok(())
}
pub fn copy_decode<R: Read, W: Write>(source: R, mut destination: W) -> io::Result<()> {
io::copy(&mut read::XzDecoder::new(source), &mut destination)?;
Ok(())
}
pub fn uncompressed_size<R: Read + Seek>(mut source: R) -> io::Result<u64> {
use std::mem::MaybeUninit;
let mut footer = [0u8; liblzma_sys::LZMA_STREAM_HEADER_SIZE as usize];
source.seek(io::SeekFrom::End(
0 - (liblzma_sys::LZMA_STREAM_HEADER_SIZE as i64),
))?;
source.read_exact(&mut footer)?;
let lzma_stream_flags = unsafe {
let mut lzma_stream_flags = MaybeUninit::uninit();
let ret =
liblzma_sys::lzma_stream_footer_decode(lzma_stream_flags.as_mut_ptr(), footer.as_ptr());
if ret != liblzma_sys::LZMA_OK {
return Err(io::Error::new(
io::ErrorKind::Other,
"Failed to parse lzma footer",
));
}
lzma_stream_flags.assume_init()
};
let index_plus_footer =
liblzma_sys::LZMA_STREAM_HEADER_SIZE as usize + lzma_stream_flags.backward_size as usize;
source.seek(io::SeekFrom::End(0 - index_plus_footer as i64))?;
let buf = source
.bytes()
.take(index_plus_footer)
.collect::<io::Result<Vec<u8>>>()?;
let uncompressed_size = unsafe {
let mut i: MaybeUninit<*mut liblzma_sys::lzma_index> = MaybeUninit::uninit();
let mut memlimit = u64::MAX;
let mut in_pos = 0usize;
let ret = liblzma_sys::lzma_index_buffer_decode(
i.as_mut_ptr(),
&mut memlimit,
std::ptr::null(),
buf.as_ptr(),
&mut in_pos,
buf.len(),
);
if ret != liblzma_sys::LZMA_OK {
return Err(io::Error::new(
io::ErrorKind::Other,
"Failed to parse lzma footer",
));
}
let i = i.assume_init();
let uncompressed_size = liblzma_sys::lzma_index_uncompressed_size(i);
liblzma_sys::lzma_index_end(i, std::ptr::null());
uncompressed_size
};
Ok(uncompressed_size)
}
#[cfg(test)]
mod tests {
use super::*;
use quickcheck::quickcheck;
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;
#[test]
fn all() {
quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let e = encode_all(&v[..], 6).unwrap();
let d = decode_all(&e[..]).unwrap();
v == d
}
}
#[test]
fn copy() {
quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let mut e = Vec::new();
copy_encode(&v[..], &mut e, 6).unwrap();
let mut d = Vec::new();
copy_decode(&e[..], &mut d).unwrap();
v == d
}
}
#[test]
fn size() {
quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let mut e = Vec::new();
copy_encode(&v[..], &mut e, 6).unwrap();
let s = super::uncompressed_size(std::io::Cursor::new(e)).unwrap();
(s as usize) == v.len()
}
}
}