aboutsummaryrefslogtreecommitdiff
path: root/objectstore/packed/delta_apply.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-02-21 18:44:45 +0800
committerGravatar Runxi Yu2026-02-21 18:44:45 +0800
commit42ff39c8d340dabce79c4057a07a3932da295772 (patch)
treef90f6f8ad9401122654409bec61a1f8ccec7bb32 /objectstore/packed/delta_apply.go
parentbufpool: Import (diff)
signatureNo signature
format/delta/apply: Move core delta apply algorithm here
Diffstat (limited to 'objectstore/packed/delta_apply.go')
-rw-r--r--objectstore/packed/delta_apply.go126
1 files changed, 2 insertions, 124 deletions
diff --git a/objectstore/packed/delta_apply.go b/objectstore/packed/delta_apply.go
index 9d34c245..a067525d 100644
--- a/objectstore/packed/delta_apply.go
+++ b/objectstore/packed/delta_apply.go
@@ -3,6 +3,7 @@ package packed
import (
"fmt"
+ deltaapply "codeberg.org/lindenii/furgit/format/delta/apply"
"codeberg.org/lindenii/furgit/objecttype"
)
@@ -27,7 +28,7 @@ func (store *Store) deltaResolveContent(start location) (objecttype.Type, []byte
if err != nil {
return objecttype.TypeInvalid, nil, err
}
- out, err = applyDelta(out, delta)
+ out, err = deltaapply.Apply(out, delta)
if err != nil {
return objecttype.TypeInvalid, nil, err
}
@@ -41,126 +42,3 @@ func (store *Store) deltaResolveContent(start location) (objecttype.Type, []byte
}
return baseType, out, nil
}
-
-// applyDelta applies one Git delta instruction stream to base.
-func applyDelta(base, delta []byte) ([]byte, error) {
- pos := 0
- srcSize, err := readDeltaVarint(delta, &pos)
- if err != nil {
- return nil, err
- }
- dstSize, err := readDeltaVarint(delta, &pos)
- if err != nil {
- return nil, err
- }
- if srcSize != len(base) {
- return nil, fmt.Errorf("objectstore/packed: delta source size mismatch: got %d want %d", srcSize, len(base))
- }
-
- out := make([]byte, dstSize)
- outPos := 0
- for pos < len(delta) {
- op := delta[pos]
- pos++
- if op&0x80 != 0 {
- off := 0
- if op&0x01 != 0 {
- if pos >= len(delta) {
- return nil, fmt.Errorf("objectstore/packed: malformed delta copy offset")
- }
- off |= int(delta[pos])
- pos++
- }
- if op&0x02 != 0 {
- if pos >= len(delta) {
- return nil, fmt.Errorf("objectstore/packed: malformed delta copy offset")
- }
- off |= int(delta[pos]) << 8
- pos++
- }
- if op&0x04 != 0 {
- if pos >= len(delta) {
- return nil, fmt.Errorf("objectstore/packed: malformed delta copy offset")
- }
- off |= int(delta[pos]) << 16
- pos++
- }
- if op&0x08 != 0 {
- if pos >= len(delta) {
- return nil, fmt.Errorf("objectstore/packed: malformed delta copy offset")
- }
- off |= int(delta[pos]) << 24
- pos++
- }
-
- n := 0
- if op&0x10 != 0 {
- if pos >= len(delta) {
- return nil, fmt.Errorf("objectstore/packed: malformed delta copy size")
- }
- n |= int(delta[pos])
- pos++
- }
- if op&0x20 != 0 {
- if pos >= len(delta) {
- return nil, fmt.Errorf("objectstore/packed: malformed delta copy size")
- }
- n |= int(delta[pos]) << 8
- pos++
- }
- if op&0x40 != 0 {
- if pos >= len(delta) {
- return nil, fmt.Errorf("objectstore/packed: malformed delta copy size")
- }
- n |= int(delta[pos]) << 16
- pos++
- }
- if n == 0 {
- n = 0x10000
- }
- if off < 0 || n < 0 || off+n > len(base) || outPos+n > len(out) {
- return nil, fmt.Errorf("objectstore/packed: delta copy out of bounds")
- }
- copy(out[outPos:outPos+n], base[off:off+n])
- outPos += n
- continue
- }
-
- if op == 0 {
- return nil, fmt.Errorf("objectstore/packed: invalid delta opcode 0")
- }
- n := int(op)
- if pos+n > len(delta) || outPos+n > len(out) {
- return nil, fmt.Errorf("objectstore/packed: delta insert out of bounds")
- }
- copy(out[outPos:outPos+n], delta[pos:pos+n])
- outPos += n
- pos += n
- }
- if outPos != len(out) {
- return nil, fmt.Errorf("objectstore/packed: delta output size mismatch: got %d want %d", outPos, len(out))
- }
- return out, nil
-}
-
-// readDeltaVarint parses one Git delta varint and advances pos.
-func readDeltaVarint(buf []byte, pos *int) (int, error) {
- value := 0
- shift := uint(0)
- for {
- if *pos >= len(buf) {
- return 0, fmt.Errorf("objectstore/packed: malformed delta varint")
- }
- b := buf[*pos]
- *pos++
- value |= int(b&0x7f) << shift
- if b&0x80 == 0 {
- break
- }
- shift += 7
- if shift > 63 {
- return 0, fmt.Errorf("objectstore/packed: delta varint overflow")
- }
- }
- return value, nil
-}