GXWDF2M2F5VA4JR6TC5RI5TFVWY7CA6C4ZW2UXGLD66Z4VSY6PMAC
MHZGMWJEW5YBHXSK77U5TCCGETWCTCQFPFC32H4URMLBTG5WMTAQC
NOSZA4ZMMICEZS4NPOE66REH2V5AWQLIUIQC7GGIKDWPNBSQFIXQC
57ARVVZEGNKP7DI5QGQWSZ22Q5T3YXXVDX2EC7PS5ITAZTLLC7HQC
IH334Q5ACWE4TNQYYOOF6GWV6CRXOEM6542NVNPA6HRIZ3CBFKEAC
HEFGMMUMJ2GGJGF2BEKF7EUL24AO53WJTXKBJSEGT64AV3Y4TBZQC
HELRYMZKHZW4S2IEYXA4IE7VOYYL7FH6TVHGFHJ4J3KRBBLHPQPAC
K6L5F26WJMIYPP3Y3CBBUYMAK7C5SVR7NYFNU45NGU5NMDCSJJIQC
6XB4RDRQIINYARVQUO3U3ZG7652UIUXBUF33U7JEJ7ASRI47EKHAC
UPRY2FELRWZCL5FGUS3EKS2RXEY7D2FGXYGLJWDNJT23PHITRWMAC
TKSHSYFM7M7CAFAJDZEZRPIIJF5PZF2GI3YRH7FEI632YQFS3AJQC
const data: &[u8; 731] = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut diam ante, sollicitudin a dolor et, volutpat elementum nulla. Etiam nec efficitur nibh, quis rutrum risus. Maecenas quis lorem malesuada, aliquet mi vel, viverra nunc. Donec et nulla sed velit sagittis varius. Suspendisse vestibulum, neque lobortis ornare vestibulum, orci turpis vulputate nisi, ut sodales neque purus eget magna. Nunc condimentum, diam eu consequat venenatis, est nisl semper lorem, et lobortis velit justo sed nulla. Nunc sit amet tempor nunc, vel posuere ipsum. Cras erat tortor, pulvinar ac pretium eu, auctor ac nibh. Duis iaculis porta magna, eu lobortis elit. Duis vitae massa eros. Nulla non magna accumsan, egestas quam sit amet, laoreet lectus.";
const DATA: &[u8; 731] = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut diam ante, sollicitudin a dolor et, volutpat elementum nulla. Etiam nec efficitur nibh, quis rutrum risus. Maecenas quis lorem malesuada, aliquet mi vel, viverra nunc. Donec et nulla sed velit sagittis varius. Suspendisse vestibulum, neque lobortis ornare vestibulum, orci turpis vulputate nisi, ut sodales neque purus eget magna. Nunc condimentum, diam eu consequat venenatis, est nisl semper lorem, et lobortis velit justo sed nulla. Nunc sit amet tempor nunc, vel posuere ipsum. Cras erat tortor, pulvinar ac pretium eu, auctor ac nibh. Duis iaculis porta magna, eu lobortis elit. Duis vitae massa eros. Nulla non magna accumsan, egestas quam sit amet, laoreet lectus.";
match *self {
Error::CouldNotOpenFile(ref f) => write!(fmt, "Could not open file {}.", f),
Error::ZSTD(r) => unsafe {
let error = CStr::from_ptr(ZSTD_getErrorName(r));
write!(fmt, "ZSTD({:?}).", error)
},
Error::Io(ref e) => e.fmt(fmt),
Error::Null => write!(fmt, "Null pointer."),
Error::FIndexTooLarge(a, b) => write!(
fmt,
"Frame index too large. Expected at most {}, found {}.",
a, b
),
Error::Generic => write!(fmt, "Error (generic)."),
Error::SeekableIo => write!(fmt, "An I/O error occurred when reading/seeking."),
Error::InvalidConversion => write!(fmt, "Invalid slice to convert from bytes to u32."),
Error::FParamUnsupported(a, b) => write!(
fmt,
"Unsupported frame parameter. Expected at most {}, found {}.",
a, b
),
Error::PrefixUnknown(p) => write!(fmt, "Unknown frame descriptor {}", p),
Error::Corruption(ref s) => write!(fmt, "Corrupted block detected {}.", s),
Error::DSizeTooSmall(a, b) => write!(
fmt,
"Destination buffer is too small. Expected at least {}, found {}.",
b, a
),
unsafe {
let error = CStr::from_ptr(ZSTD_getErrorName(self.0));
write!(fmt, "{}", error.to_str().unwrap())
let dstream = unsafe { ZSTD_createDStream() };
if dstream.is_null() {
return Err(Error::Null);
unsafe {
let dstream = ZSTD_createDStream();
if dstream.is_null() {
Err(Error::Null)
} else {
Ok(Seekable {
dstream,
seek_table: SeekTable::new(),
src: source,
inner_buf_size: size,
decompressed_offset: 0,
cur_frame: 0,
in_buff: vec![0; SEEKABLE_BUFF_SIZE],
out_buff: vec![0; SEEKABLE_BUFF_SIZE],
xxh_state: Xxh64::new(0),
})
}
#[test]
fn pijul_change() {
let mut h = xxhash_rust::xxh64::Xxh64::new(0);
h.update(&[4]);
let d = 0x64b9da3ed69d6732;
let f = h.finish();
assert_eq!(d, f);
let change = include_bytes!("../../.pijul/changes/IH/334Q5ACWE4TNQYYOOF6GWV6CRXOEM6542NVNPA6HRIZ3CBFKEAC.change");
use serde_derive::*;
#[derive(Deserialize)]
pub struct Offsets {
pub version: u64,
pub hashed_len: u64,
pub unhashed_off: u64,
pub unhashed_len: u64,
pub contents_off: u64,
pub contents_len: u64,
pub total: u64,
}
let off0 = std::mem::size_of::<Offsets>();
let offsets: Offsets = bincode::deserialize(&change[..off0]).unwrap();
let mut s = Seekable::init_buf(
&change[off0..offsets.unhashed_off as usize],
).unwrap();
let mut buf_ = Vec::new();
buf_.resize(offsets.hashed_len as usize, 0);
s.decompress(&mut buf_[..], 0).unwrap();
}
impl<const N: usize> Dst for [u8; N] {
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 {
N
#[cfg(feature = "threadpool")]
mod parallel_compress {
use super::*;
use xxhash_rust::xxh64::xxh64;
pub trait Dst: Send {
fn as_mut_ptr(&mut self) -> *mut u8;
fn as_slice(&self) -> &[u8];
fn len(&self) -> usize;
fn new() -> Self;
fn new() -> Self {
unsafe { std::mem::MaybeUninit::uninit().assume_init() }
impl<const N: usize> Dst for [u8; N] {
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 {
N
}
fn new() -> Self {
unsafe { std::mem::MaybeUninit::uninit().assume_init() }
}
let ret = unsafe {
let ret = ZSTD_compress(
dst.as_mut_ptr() as *mut c_void,
dst.len() as size_t,
src.as_ptr() as *const c_void,
src.len() as size_t,
level as c_int,
);
let ret = unsafe {
let ret = ZSTD_compress(
dst.as_mut_ptr() as *mut c_void,
dst.len() as size_t,
src.as_ptr() as *const c_void,
src.len() as size_t,
level as c_int,
);
pub fn parallel_compress<W: std::io::Write, D: Dst + 'static>(
src: &'static [u8],
mut output: W,
level: usize,
jobs: usize,
chunk_size: usize,
) -> Result<(), Error> {
use std::sync::mpsc::channel;
use threadpool::ThreadPool;
pub fn parallel_compress<W: std::io::Write, D: Dst + 'static>(
src: &'static [u8],
mut output: W,
level: usize,
jobs: usize,
chunk_size: usize,
) -> Result<(), Error> {
use std::sync::mpsc::channel;
use threadpool::ThreadPool;
let (tx, rx) = channel();
for (i, chunk) in src.chunks(chunk_size).enumerate() {
let tx = tx.clone();
pool.execute(move || {
let frame = compress_frame(chunk, level);
tx.send((i, frame))
.expect("channel will be there waiting for the pool");
});
}
let (tx, rx) = channel();
for (i, chunk) in src.chunks(chunk_size).enumerate() {
let tx = tx.clone();
pool.execute(move || {
let frame = compress_frame(chunk, level);
tx.send((i, frame))
.expect("channel will be there waiting for the pool");
});
}
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?;
}
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?;
}
let mut log = FrameLog::new();
for frame in frames.iter() {
output.write_all(frame.as_slice())?;
log.log_frame(frame.dst_size, frame.src_size, frame.checksum)?;
let mut log = FrameLog::new();
for frame in frames.iter() {
output.write_all(frame.as_slice())?;
log.log_frame(frame.dst_size, frame.src_size, frame.checksum)?;
}
log.write_all(&mut output)?;
Ok(())
#[cfg(feature = "threadpool")]
pub use parallel_compress::*;
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",