Git 如何对zlib数据进行放气并找出有多少个输入字节?
我正在Rust中构建git克隆实现。我已经到了需要解析packfile来创建索引的部分,我几乎完成了解析 packfile中的每个对象都包含一个头(我已经正确解析了),后面是zlib压缩的内容 值得注意的是,存储在报头中的大小是解压缩后的大小,因此大于我们必须跳过才能到达下一个报头的实际数据 Crates.io显示了两个执行zlib解压缩并有多个下载的板条箱:Git 如何对zlib数据进行放气并找出有多少个输入字节?,git,rust,zlib,Git,Rust,Zlib,我正在Rust中构建git克隆实现。我已经到了需要解析packfile来创建索引的部分,我几乎完成了解析 packfile中的每个对象都包含一个头(我已经正确解析了),后面是zlib压缩的内容 值得注意的是,存储在报头中的大小是解压缩后的大小,因此大于我们必须跳过才能到达下一个报头的实际数据 Crates.io显示了两个执行zlib解压缩并有多个下载的板条箱: libzsys:实际上是一个hello世界,几个月来一直如此 flate2:这样可以轻松正确地对数据进行放气: print!("Obj
:实际上是一个hello世界,几个月来一直如此libzsys
:这样可以轻松正确地对数据进行放气:flate2
print!("Object type {} size {}", obj_type as u8, obj_size); println!(" data:\n{}", String::from_utf8( ZlibDecoder::new(data).read_exact(obj_size as usize).unwrap() ).unwrap() );
ZlibDecoder
没有提供任何方法来检测输入有多大
它将读者的所有权作为输入,而不是引用
因此,即使我有对象的输出大小(实际上还有对象的所有数据),因为我不知道输入大小,我也无法开始读取下一个对象头
如何获得达到预期输出大小所需的压缩输入字节数?如果可能,我希望避免使用FFI调用本机zlib
注:
flate2
文档建议使用一个适配器,但我不知道这对我有什么帮助,或者这是否会帮助我正常情况下,您可以将引用传递给读写器(通过或),以允许向流添加适配器,而不会失去对它的控制。像这样的方法应该会奏效:
问题的出现是因为2号公寓是空的。它总是尽可能多地填充自己的内部缓冲区,即使其中一些数据不会被读取。这种可怕的、令人讨厌的黑客行为导致它一次只能读取一个字节。因此,您可以在末尾倒带一个字节,然后重新开始
一个长期的解决方案可能是添加一个访问器,最多访问一次,然后直到您到达
ZlibDecoder
一个可怕的讨厌的黑客正是医生命令的!
#![feature(io,path,env)]
extern crate flate2;
use flate2::CompressionLevel;
use flate2::writer::ZlibEncoder;
use flate2::reader::ZlibDecoder;
use std::env;
use std::old_io::File;
use std::old_io::{ByRefReader,ByRefWriter};
use std::old_path::Path;
fn main() {
let path = "./data";
let write = env::var("WRITE").is_ok();
if write {
println!("Writing to {}", path);
let mut f = File::create(&Path::new(path)).unwrap();
fn write_it<W>(w: &mut W, s: &str) where W: Writer {
let mut z = ZlibEncoder::new(ByRefWriter::by_ref(w), CompressionLevel::Default);
z.write_all(s.as_bytes()).unwrap();
}
write_it(&mut f, "hello world");
write_it(&mut f, "goodbye world");
} else {
println!("Reading from {}", path);
let mut f = File::open(&Path::new(path)).unwrap();
fn read_it<R>(r: &mut R) -> String where R: Reader {
let mut z = ZlibDecoder::new(ByRefReader::by_ref(r));
z.read_to_string().unwrap()
}
println!("{}", read_it(&mut f));
println!("{}", read_it(&mut f));
}
}
fn read_it<R>(r: &mut R) -> String where R: Reader {
let mut z = ZlibDecoder::new_with_buf(ByRefReader::by_ref(r), Vec::with_capacity(1));
z.read_to_string().unwrap()
}
println!("{}", read_it(&mut f));
f.seek(-1, std::old_io::SeekStyle::SeekCur);
println!("{}", read_it(&mut f));