summaryrefslogtreecommitdiffstats
path: root/vendor/gix-pack/src/data/delta.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix-pack/src/data/delta.rs
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-pack/src/data/delta.rs')
-rw-r--r--vendor/gix-pack/src/data/delta.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/vendor/gix-pack/src/data/delta.rs b/vendor/gix-pack/src/data/delta.rs
new file mode 100644
index 000000000..a898e4aaf
--- /dev/null
+++ b/vendor/gix-pack/src/data/delta.rs
@@ -0,0 +1,70 @@
+/// Given the decompressed pack delta `d`, decode a size in bytes (either the base object size or the result object size)
+/// Equivalent to [this canonical git function](https://github.com/git/git/blob/311531c9de557d25ac087c1637818bd2aad6eb3a/delta.h#L89)
+pub fn decode_header_size(d: &[u8]) -> (u64, usize) {
+ let mut i = 0;
+ let mut size = 0u64;
+ let mut consumed = 0;
+ for cmd in d.iter() {
+ consumed += 1;
+ size |= (*cmd as u64 & 0x7f) << i;
+ i += 7;
+ if *cmd & 0x80 == 0 {
+ break;
+ }
+ }
+ (size, consumed)
+}
+
+pub fn apply(base: &[u8], mut target: &mut [u8], data: &[u8]) {
+ let mut i = 0;
+ while let Some(cmd) = data.get(i) {
+ i += 1;
+ match cmd {
+ cmd if cmd & 0b1000_0000 != 0 => {
+ let (mut ofs, mut size): (u32, u32) = (0, 0);
+ if cmd & 0b0000_0001 != 0 {
+ ofs = data[i] as u32;
+ i += 1;
+ }
+ if cmd & 0b0000_0010 != 0 {
+ ofs |= (data[i] as u32) << 8;
+ i += 1;
+ }
+ if cmd & 0b0000_0100 != 0 {
+ ofs |= (data[i] as u32) << 16;
+ i += 1;
+ }
+ if cmd & 0b0000_1000 != 0 {
+ ofs |= (data[i] as u32) << 24;
+ i += 1;
+ }
+ if cmd & 0b0001_0000 != 0 {
+ size = data[i] as u32;
+ i += 1;
+ }
+ if cmd & 0b0010_0000 != 0 {
+ size |= (data[i] as u32) << 8;
+ i += 1;
+ }
+ if cmd & 0b0100_0000 != 0 {
+ size |= (data[i] as u32) << 16;
+ i += 1;
+ }
+ if size == 0 {
+ size = 0x10000; // 65536
+ }
+ let ofs = ofs as usize;
+ std::io::Write::write(&mut target, &base[ofs..ofs + size as usize])
+ .expect("delta copy from base: byte slices must match");
+ }
+ 0 => panic!("encountered unsupported command code: 0"),
+ size => {
+ std::io::Write::write(&mut target, &data[i..i + *size as usize])
+ .expect("delta copy data: slice sizes to match up");
+ i += *size as usize;
+ }
+ }
+ }
+ assert_eq!(i, data.len());
+ assert_eq!(target.len(), 0);
+}