aboutsummaryrefslogtreecommitdiff
path: root/objectid/algorithms.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-04 09:23:23 +0800
committerGravatar Runxi Yu2026-03-04 09:23:23 +0800
commit4905605124ab0ea390cdd65963d5a6a1a5258c45 (patch)
tree88e6a7f22354f8b4e1ce9e0fcc6f72499aa14d56 /objectid/algorithms.go
parentlint: Quick fix (diff)
signatureNo signature
objectid: File splitting
Diffstat (limited to 'objectid/algorithms.go')
-rw-r--r--objectid/algorithms.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/objectid/algorithms.go b/objectid/algorithms.go
new file mode 100644
index 00000000..0a8d4517
--- /dev/null
+++ b/objectid/algorithms.go
@@ -0,0 +1,127 @@
+package objectid
+
+import (
+ "crypto/sha1" //#nosec gosec
+ "crypto/sha256"
+ "hash"
+)
+
+// maxObjectIDSize MUST be >= the largest supported algorithm size.
+const maxObjectIDSize = sha256.Size
+
+// Algorithm identifies the hash algorithm used for Git object IDs.
+type Algorithm uint8
+
+const (
+ AlgorithmUnknown Algorithm = iota
+ AlgorithmSHA1
+ AlgorithmSHA256
+)
+
+type algorithmDetails struct {
+ name string
+ size int
+ sum func([]byte) ObjectID
+ new func() hash.Hash
+}
+
+var algorithmTable = [...]algorithmDetails{
+ AlgorithmUnknown: {},
+ AlgorithmSHA1: {
+ name: "sha1",
+ size: sha1.Size,
+ sum: func(data []byte) ObjectID {
+ sum := sha1.Sum(data) //#nosec G401
+
+ var id ObjectID
+ copy(id.data[:], sum[:])
+ id.algo = AlgorithmSHA1
+
+ return id
+ },
+ new: sha1.New,
+ },
+ AlgorithmSHA256: {
+ name: "sha256",
+ size: sha256.Size,
+ sum: func(data []byte) ObjectID {
+ sum := sha256.Sum256(data)
+
+ var id ObjectID
+ copy(id.data[:], sum[:])
+ id.algo = AlgorithmSHA256
+
+ return id
+ },
+ new: sha256.New,
+ },
+}
+
+var (
+ algorithmByName = map[string]Algorithm{}
+ supportedAlgorithms []Algorithm
+)
+
+func init() { //nolint:gochecknoinits
+ for algo := Algorithm(0); int(algo) < len(algorithmTable); algo++ {
+ info := algorithmTable[algo]
+ if info.name == "" {
+ continue
+ }
+
+ algorithmByName[info.name] = algo
+ supportedAlgorithms = append(supportedAlgorithms, algo)
+ }
+}
+
+// SupportedAlgorithms returns all object ID algorithms supported by furgit.
+// Do not mutate.
+func SupportedAlgorithms() []Algorithm {
+ return supportedAlgorithms
+}
+
+// ParseAlgorithm parses a canonical algorithm name (e.g. "sha1", "sha256").
+func ParseAlgorithm(s string) (Algorithm, bool) {
+ algo, ok := algorithmByName[s]
+
+ return algo, ok
+}
+
+// Size returns the hash size in bytes.
+func (algo Algorithm) Size() int {
+ return algo.info().size
+}
+
+// String returns the canonical algorithm name.
+func (algo Algorithm) String() string {
+ inf := algo.info()
+ if inf.name == "" {
+ return "unknown"
+ }
+
+ return inf.name
+}
+
+// HexLen returns the encoded hexadecimal length.
+func (algo Algorithm) HexLen() int {
+ return algo.Size() * 2
+}
+
+// Sum computes an object ID from raw data using the selected algorithm.
+func (algo Algorithm) Sum(data []byte) ObjectID {
+ return algo.info().sum(data)
+}
+
+// New returns a new hash.Hash for this algorithm.
+func (algo Algorithm) New() (hash.Hash, error) {
+ newFn := algo.info().new
+ if newFn == nil {
+ return nil, ErrInvalidAlgorithm
+ }
+
+ return newFn(), nil
+}
+
+func (algo Algorithm) info() algorithmDetails {
+ return algorithmTable[algo]
+}