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!
Unified · Split
| @@ -248,7 +248,6 @@ impl File { · 247 unmodified lines | |||
| 248 | let (result_size, consumed) = delta_header_size(&buf[consumed..]); | 248 | let (result_size, consumed) = delta_header_size(&buf[consumed..]); |
| 249 | delta.header_size += consumed; | 249 | delta.header_size += consumed; |
| 250 | delta.result_size = result_size; | 250 | delta.result_size = result_size; |
| 251 | dbg!(delta); | ||
| 252 | } | 251 | } |
| 253 | 252 | ||
| 254 | // From oldest to most recent, apply all deltas, swapping the buffer back and forth | 253 | // From oldest to most recent, apply all deltas, swapping the buffer back and forth |
| @@ -285,8 +284,50 @@ impl File { · 30 unmodified lines | |||
| 285 | } | 284 | } |
| 286 | } | 285 | } |
| 287 | 286 | ||
| 288 | fn apply_delta(source: &[u8], target: &mut [u8], instructions: &[u8]) { | 287 | fn apply_delta(mut base: &[u8], mut target: &mut [u8], instructions: &[u8]) { |
| 289 | unimplemented!("delta application") | 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 | } | ||
| 290 | } | 331 | } |
| 291 | 332 | ||
| 292 | fn delta_header_size(d: &[u8]) -> (u64, usize) { | 333 | fn delta_header_size(d: &[u8]) -> (u64, usize) { |