ref: b46eba214daa9a6ede179ed543033b0f3485ec2e
dir: /objectid/objectid.go/
// Package objectid provides utilities around object IDs and hash algorithms.
package objectid
import (
//#nosec G505
"bytes"
"encoding/hex"
"fmt"
)
// ObjectID represents a Git object ID.
//
//nolint:recvcheck
type ObjectID struct {
algo Algorithm
data [maxObjectIDSize]byte
}
// Algorithm returns the object ID's hash algorithm.
func (id ObjectID) Algorithm() Algorithm {
return id.algo
}
// Size returns the object ID size in bytes.
func (id ObjectID) Size() int {
return id.algo.Size()
}
// String returns the canonical hex representation.
func (id ObjectID) String() string {
size := id.Size()
return hex.EncodeToString(id.data[:size])
}
// Bytes returns a copy of the object ID bytes.
func (id ObjectID) Bytes() []byte {
size := id.Size()
return append([]byte(nil), id.data[:size]...)
}
// RawBytes returns a direct byte slice view of the object ID bytes.
//
// The returned slice aliases the object ID's internal storage. Callers MUST
// treat it as read-only and MUST NOT modify its contents.
//
// Use Bytes when an independent copy is required.
func (id *ObjectID) RawBytes() []byte {
size := id.Size()
return id.data[:size:size]
}
// Compare lexicographically compares two object IDs by their canonical byte
// representation.
func Compare(left, right ObjectID) int {
return bytes.Compare(left.RawBytes(), right.RawBytes())
}
// Zero returns the all-zero object ID for the specified algorithm.
func Zero(algo Algorithm) ObjectID {
id, err := FromBytes(algo, make([]byte, algo.Size()))
if err != nil {
panic(err)
}
return id
}
// ParseHex parses an object ID from hex for the specified algorithm.
func ParseHex(algo Algorithm, s string) (ObjectID, error) {
var id ObjectID
if algo.Size() == 0 {
return id, ErrInvalidAlgorithm
}
if len(s)%2 != 0 {
return id, fmt.Errorf("%w: odd hex length %d", ErrInvalidObjectID, len(s))
}
if len(s) != algo.HexLen() {
return id, fmt.Errorf("%w: got %d chars, expected %d", ErrInvalidObjectID, len(s), algo.HexLen())
}
decoded, err := hex.DecodeString(s)
if err != nil {
return id, fmt.Errorf("%w: decode: %w", ErrInvalidObjectID, err)
}
copy(id.data[:], decoded)
id.algo = algo
return id, nil
}
// FromBytes builds an object ID from raw bytes for the specified algorithm.
func FromBytes(algo Algorithm, b []byte) (ObjectID, error) {
var id ObjectID
if algo.Size() == 0 {
return id, ErrInvalidAlgorithm
}
if len(b) != algo.Size() {
return id, fmt.Errorf("%w: got %d bytes, expected %d", ErrInvalidObjectID, len(b), algo.Size())
}
copy(id.data[:], b)
id.algo = algo
return id, nil
}