aboutsummaryrefslogtreecommitdiff
path: root/format/packfile/entry_header.go
blob: 056642680b9848f9e73c5c6b2afc1ba288cf4176 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package packfile

import (
	"fmt"

	objecttype "codeberg.org/lindenii/furgit/object/type"
)

// 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
}