aboutsummaryrefslogtreecommitdiff
path: root/object/store/packed/internal/ingest/header.go
blob: 6b90becc2f55d02f99a0cea8c0a294344f78f833 (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
53
54
package ingest

import (
	"encoding/binary"
	"fmt"
	"io"

	"codeberg.org/lindenii/furgit/format/packfile"
)

const packHeaderSize = 12

type packHeader struct {
	Version     uint32
	ObjectCount uint32
}

// readAndValidatePackHeader reads one PACK header from src and validates it.
func readAndValidatePackHeader(src io.Reader) (packHeader, [packHeaderSize]byte, error) {
	var hdr [packHeaderSize]byte

	_, err := io.ReadFull(src, hdr[:])
	if err != nil {
		return packHeader{}, [packHeaderSize]byte{}, &InvalidPackHeaderError{
			Reason: fmt.Sprintf("read header: %v", err),
		}
	}

	header, err := parseAndValidatePackHeader(hdr)
	if err != nil {
		return packHeader{}, [packHeaderSize]byte{}, err
	}

	return header, hdr, nil
}

// parseAndValidatePackHeader validates one already-read PACK header.
func parseAndValidatePackHeader(hdr [packHeaderSize]byte) (packHeader, error) {
	if binary.BigEndian.Uint32(hdr[:4]) != packfile.Signature {
		return packHeader{}, &InvalidPackHeaderError{Reason: "signature mismatch"}
	}

	version := binary.BigEndian.Uint32(hdr[4:8])
	if !packfile.SupportedVersion(version) {
		return packHeader{}, &InvalidPackHeaderError{
			Reason: fmt.Sprintf("unsupported version %d", version),
		}
	}

	return packHeader{
		Version:     version,
		ObjectCount: binary.BigEndian.Uint32(hdr[8:12]),
	}, nil
}