History

first version of delta-apply, with a fatal flaw :D

It's interesting how low-level operations on bytes can be a bit troublesome in purely safe and potentially high-level Rust with iterators. Git, anyway, really wants free access to memory in this case!

Sebastian Thiel committed 6 years ago

Commit f38ec001 parent a9000081 file · +44 −3Browse files

Unified · Split

gitoxide-odb/src/pack/file/mod.rs+44−3
@@ -248,7 +248,6 @@ impl File { · 247 unmodified lines
248248 let (result_size, consumed) = delta_header_size(&buf[consumed..]);
249249 delta.header_size += consumed;
250250 delta.result_size = result_size;
251− dbg!(delta);
252251 }
253252
254253 // From oldest to most recent, apply all deltas, swapping the buffer back and forth
@@ -285,8 +284,50 @@ impl File { · 30 unmodified lines
285284 }
286285 }
287286
288−fn apply_delta(source: &[u8], target: &mut [u8], instructions: &[u8]) {
289− unimplemented!("delta application")
287+fn apply_delta(mut base: &[u8], mut target: &mut [u8], instructions: &[u8]) {
288+ let mut iter = instructions.into_iter();
289+ while let Some(cmd) = iter.next() {
290+ match cmd {
291+ cmd if cmd & 0b1000_0000 != 0 => {
292+ let (mut ofs, mut size): (u32, u32) = (0, 0);
293+ if cmd & 0b0000_0001 != 0 {
294+ ofs = *iter.next().unwrap() as u32;
295+ }
296+ if cmd & 0b0000_0010 != 0 {
297+ ofs |= (*iter.next().unwrap() as u32) << 8;
298+ }
299+ if cmd & 0b0000_0100 != 0 {
300+ ofs |= (*iter.next().unwrap() as u32) << 16;
301+ }
302+ if cmd & 0b0000_1000 != 0 {
303+ ofs |= (*iter.next().unwrap() as u32) << 24;
304+ }
305+ if cmd & 0b0001_0000 != 0 {
306+ size = *iter.next().unwrap() as u32;
307+ }
308+ if cmd & 0b0010_0000 != 0 {
309+ size |= (*iter.next().unwrap() as u32) << 8;
310+ }
311+ if cmd & 0b0100_0000 != 0 {
312+ size |= (*iter.next().unwrap() as u32) << 16;
313+ }
314+ if size == 0 {
315+ size = 0x10000; // 65536
316+ }
317+ let ofs = ofs as usize;
318+ std::io::Write::write(&mut target, &base[ofs..ofs + size as usize])
319+ .expect("delta copy from base: byte slices must match");
320+ }
321+ 0 => panic!("encounted unsupported command code: 0"),
322+ size => {
323+ // Fixme: must copy from instruction buffer!
324+ let (dest, rest) = base.split_at(*size as usize);
325+ std::io::Write::write(&mut target, dest)
326+ .expect("delta copy data: slice sizes to match up");
327+ base = rest;
328+ }
329+ }
330+ }
290331 }
291332
292333 fn delta_header_size(d: &[u8]) -> (u64, usize) {