aboutsummaryrefslogtreecommitdiff
path: root/packfile/entry_header.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-12 10:01:32 +0800
committerGravatar Runxi Yu2026-03-12 10:01:32 +0800
commitf74018c19970d11a7ba0c89e581cb9f86c0d3c14 (patch)
tree9787292fb089641ffb9f6bc91cfb92fc97e8f833 /packfile/entry_header.go
parentrefstore: More fixes on ResolveToDetached (diff)
signatureNo signature
packfile: Split to many files
Diffstat (limited to 'packfile/entry_header.go')
-rw-r--r--packfile/entry_header.go52
1 files changed, 52 insertions, 0 deletions
diff --git a/packfile/entry_header.go b/packfile/entry_header.go
new file mode 100644
index 00000000..b7f8e79c
--- /dev/null
+++ b/packfile/entry_header.go
@@ -0,0 +1,52 @@
+package packfile
+
+import (
+ "fmt"
+
+ "codeberg.org/lindenii/furgit/objecttype"
+)
+
+// EntryHeader is one parsed pack entry header prefix.
+type EntryHeader struct {
+ // Type is the entry type tag from the first header byte.
+ Type objecttype.Type
+ // Size is the declared resulting object size.
+ Size int64
+ // HeaderSize is the number of bytes consumed by the type/size header.
+ HeaderSize int
+}
+
+// ParseEntryHeader parses one pack entry type/size header from data.
+func ParseEntryHeader(data []byte) (EntryHeader, error) {
+ var zero EntryHeader
+ if len(data) == 0 {
+ return zero, fmt.Errorf("packfile: truncated entry header")
+ }
+
+ first := data[0]
+ header := EntryHeader{
+ Type: objecttype.Type((first >> 4) & 0x07),
+ Size: int64(first & 0x0f),
+ HeaderSize: 1,
+ }
+
+ shift := uint(4)
+
+ b := first
+ for b&0x80 != 0 {
+ if header.HeaderSize >= len(data) {
+ return zero, fmt.Errorf("packfile: truncated entry header")
+ }
+
+ b = data[header.HeaderSize]
+ header.HeaderSize++
+ header.Size |= int64(b&0x7f) << shift
+ shift += 7
+ }
+
+ if header.Size < 0 {
+ return zero, fmt.Errorf("packfile: negative entry size")
+ }
+
+ return header, nil
+}