From 4948cf43105e28e0bbfdb4d15d3e7ad63426860b Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Fri, 12 Jun 2026 14:18:48 +0000 Subject: internal/format/packfile: Add header parser --- internal/format/packfile/header.go | 64 +++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 5 deletions(-) (limited to 'internal/format') diff --git a/internal/format/packfile/header.go b/internal/format/packfile/header.go index 1a156f36..64c7d140 100644 --- a/internal/format/packfile/header.go +++ b/internal/format/packfile/header.go @@ -1,9 +1,63 @@ package packfile -// Signature is the 4-byte "PACK" magic at the start of pack files. -const Signature = 0x5041434b +import ( + "encoding/binary" + "errors" + "fmt" +) -// SupportedVersion reports whether a pack version is supported. -func SupportedVersion(version uint32) bool { - return version == 2 +const ( + // signature is the 4-byte "PACK" magic at the start of pack files. + signature = 0x5041434b + + // version is the only pack version this package reads or writes. + version = 2 +) + +// HeaderLen is the size of a pack header: +// signature, version, and object count. +const HeaderLen = 12 + +// ErrMalformedHeader reports that +// a pack header is truncated, +// or has a bad signature or unsupported version. +var ErrMalformedHeader = errors.New("internal/format/packfile: malformed pack header") + +// Header is one parsed pack header. +type Header struct { + // ObjectCount is the number of object entries + // declared to follow the header. + ObjectCount uint32 +} + +// ParseHeader parses and validates the pack header +// at the start of data. +func ParseHeader(data []byte) (Header, error) { + var zero Header + + if len(data) < HeaderLen { + return zero, fmt.Errorf("%w: truncated", ErrMalformedHeader) + } + + if binary.BigEndian.Uint32(data[0:4]) != signature { + return zero, fmt.Errorf("%w: bad signature", ErrMalformedHeader) + } + + parsedVersion := binary.BigEndian.Uint32(data[4:8]) + if parsedVersion != version { + return zero, fmt.Errorf("%w: unsupported version %d", ErrMalformedHeader, parsedVersion) + } + + return Header{ + ObjectCount: binary.BigEndian.Uint32(data[8:12]), + }, nil +} + +// AppendHeader appends an encoded pack header for objectCount to dst. +func AppendHeader(dst []byte, objectCount uint32) []byte { + dst = binary.BigEndian.AppendUint32(dst, signature) + dst = binary.BigEndian.AppendUint32(dst, version) + dst = binary.BigEndian.AppendUint32(dst, objectCount) + + return dst } -- cgit v1.3.1-10-gc9f91