Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
@@ -0,0 +1,108 @@
use crate::{lzma::params::LzmaDecoderParams, xz2::process_stream, DecodeV2, DecodedSize};
use compression_core::util::{PartialBuffer, WriteBuffer};
use liblzma::stream::{Action, Stream};
use std::{
convert::TryFrom,
fmt,
io::{self, Cursor},
};
/// Xz2 decoding stream
pub struct Xz2Decoder {
stream: Stream,
params: LzmaDecoderParams,
}
impl fmt::Debug for Xz2Decoder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Xz2Decoder").finish_non_exhaustive()
}
}
impl TryFrom<LzmaDecoderParams> for Xz2Decoder {
type Error = liblzma::stream::Error;
fn try_from(params: LzmaDecoderParams) -> Result<Self, Self::Error> {
let stream = Stream::try_from(&params)?;
Ok(Self { stream, params })
}
}
impl Xz2Decoder {
pub fn new(mem_limit: u64) -> Self {
let params = LzmaDecoderParams::Auto {
mem_limit,
flags: 0,
};
Self::try_from(params).unwrap()
}
#[cfg(feature = "xz-parallel")]
pub fn parallel(threads: std::num::NonZeroU32, mem_limit: u64) -> Self {
use crate::lzma::params::MtStreamBuilder;
let mut builder = MtStreamBuilder::default();
builder
.threads(threads)
.timeout_ms(300)
.mem_limit_stop(mem_limit);
let params = LzmaDecoderParams::MultiThread { builder };
Self::try_from(params).unwrap()
}
}
impl DecodeV2 for Xz2Decoder {
fn reinit(&mut self) -> io::Result<()> {
*self = Self::try_from(self.params.clone())?;
Ok(())
}
fn decode(
&mut self,
input: &mut PartialBuffer<&[u8]>,
output: &mut WriteBuffer<'_>,
) -> io::Result<bool> {
process_stream(&mut self.stream, input, output, Action::Run)
}
fn flush(&mut self, _output: &mut WriteBuffer<'_>) -> io::Result<bool> {
// While decoding flush is a noop
Ok(true)
}
fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
process_stream(
&mut self.stream,
&mut PartialBuffer::new(&[]),
output,
Action::Finish,
)
}
}
impl DecodedSize for Xz2Decoder {
fn decoded_size(input: &[u8]) -> io::Result<u64> {
let cursor = Cursor::new(input);
liblzma::uncompressed_size(cursor)
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
use crate::{
lzma::params::{LzmaDecoderParams, LzmaFilter, LzmaFilters, LzmaOptions},
Xz2Decoder,
};
#[test]
fn test_lzma_decoder_from_params() {
let filters = LzmaFilters::default().add_filter(LzmaFilter::Lzma2(LzmaOptions::default()));
let params = LzmaDecoderParams::Raw { filters };
Xz2Decoder::try_from(params).unwrap();
}
}
@@ -0,0 +1,116 @@
use compression_core::{
util::{PartialBuffer, WriteBuffer},
Level,
};
use liblzma::stream::{Action, Check, Stream};
use std::{
convert::{TryFrom, TryInto},
fmt, io,
};
use crate::{
lzma::params::{LzmaEncoderParams, LzmaOptions},
xz2::process_stream,
EncodeV2, Xz2FileFormat,
};
/// Xz2 encoding stream
pub struct Xz2Encoder {
stream: Stream,
params: LzmaEncoderParams,
}
impl fmt::Debug for Xz2Encoder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Xz2Encoder").finish_non_exhaustive()
}
}
impl TryFrom<LzmaEncoderParams> for Xz2Encoder {
type Error = liblzma::stream::Error;
fn try_from(params: LzmaEncoderParams) -> Result<Self, Self::Error> {
let stream = Stream::try_from(&params)?;
Ok(Self {
stream,
params: params.clone(),
})
}
}
fn xz2_level(level: Level) -> u32 {
match level {
Level::Fastest => 0,
Level::Best => 9,
Level::Precise(quality) => quality.try_into().unwrap_or(0).clamp(0, 9),
_ => 5,
}
}
impl Xz2Encoder {
pub fn new(format: Xz2FileFormat, level: Level) -> Self {
let preset = xz2_level(level);
let params = match format {
Xz2FileFormat::Xz => LzmaEncoderParams::Easy {
preset,
check: Check::Crc64,
},
Xz2FileFormat::Lzma => {
let options = LzmaOptions::default().preset(preset);
LzmaEncoderParams::Lzma { options }
}
};
Self::try_from(params).unwrap()
}
#[cfg(feature = "xz-parallel")]
pub fn xz_parallel(level: Level, threads: std::num::NonZeroU32) -> Self {
use crate::lzma::params::MtStreamBuilder;
let preset = xz2_level(level);
let mut builder = MtStreamBuilder::default();
builder
.threads(threads)
.timeout_ms(300)
.preset(preset)
.check(Check::Crc64);
let params = LzmaEncoderParams::MultiThread { builder };
Self::try_from(params).unwrap()
}
}
impl EncodeV2 for Xz2Encoder {
fn encode(
&mut self,
input: &mut PartialBuffer<&[u8]>,
output: &mut WriteBuffer<'_>,
) -> io::Result<()> {
process_stream(&mut self.stream, input, output, Action::Run).map(|_| ())
}
fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
let action = match &self.params {
// Multi-threaded streams don't support SyncFlush, use FullFlush instead
#[cfg(feature = "xz-parallel")]
LzmaEncoderParams::MultiThread { builder: _ } => Action::FullFlush,
_ => Action::SyncFlush,
};
process_stream(
&mut self.stream,
&mut PartialBuffer::new(&[]),
output,
action,
)
}
fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
process_stream(
&mut self.stream,
&mut PartialBuffer::new(&[]),
output,
Action::Finish,
)
}
}
+40
View File
@@ -0,0 +1,40 @@
mod decoder;
mod encoder;
#[derive(Debug)]
pub enum Xz2FileFormat {
Xz,
Lzma,
}
pub use self::{decoder::Xz2Decoder, encoder::Xz2Encoder};
use compression_core::util::{PartialBuffer, WriteBuffer};
use liblzma::stream::{Action, Status, Stream};
use std::io;
/// Return `Ok(true)` if stream ends.
fn process_stream(
stream: &mut Stream,
input: &mut PartialBuffer<&[u8]>,
output: &mut WriteBuffer<'_>,
action: Action,
) -> io::Result<bool> {
let previous_in = stream.total_in() as usize;
let previous_out = stream.total_out() as usize;
// Safety: We **trust** liblzma to not write uninitialized bytes into the buffer
let status =
stream.process_uninit(input.unwritten(), unsafe { output.unwritten_mut() }, action)?;
input.advance(stream.total_in() as usize - previous_in);
// Safety: We **trust** liblzma to write bytes into the buffer properly
unsafe { output.assume_init_and_advance(stream.total_out() as usize - previous_out) };
match status {
Status::Ok => Ok(false),
Status::StreamEnd => Ok(true),
Status::GetCheck => Err(io::Error::other("Unexpected lzma integrity check")),
Status::MemNeeded => Err(io::ErrorKind::OutOfMemory.into()),
}
}