diff options
Diffstat (limited to 'hash.go')
| -rw-r--r-- | hash.go | 112 |
1 files changed, 70 insertions, 42 deletions
@@ -6,59 +6,74 @@ import ( "encoding/hex" ) -// maxHashSize MUST be equal to (or larger than) the size of the -// largest hash supported in hashFuncs. +// maxHashSize MUST be >= the largest supported algorithm size. const maxHashSize = sha256.Size // hashAlgorithm identifies the hash algorithm used for Git object IDs. type hashAlgorithm uint8 -// hashFuncs maps hash algorithm to hash function. -var hashFuncs = map[hashAlgorithm]hashFunc{ - hashAlgoSHA1: func(data []byte) Hash { - sum := sha1.Sum(data) - var h Hash - copy(h.data[:], sum[:]) - h.algo = hashAlgoSHA1 - return h - }, - hashAlgoSHA256: func(data []byte) Hash { - sum := sha256.Sum256(data) - var h Hash - copy(h.data[:], sum[:]) - h.algo = hashAlgoSHA256 - return h - }, -} - const ( hashAlgoUnknown hashAlgorithm = iota hashAlgoSHA1 hashAlgoSHA256 ) -// size returns the hash size in bytes. -func (algo hashAlgorithm) size() int { - switch algo { - case hashAlgoSHA1: - return sha1.Size - case hashAlgoSHA256: - return sha256.Size - default: - return 0 - } +type hashAlgorithmDetails struct { + name string + size int + sum func([]byte) Hash +} + +var hashAlgorithmTable = [...]hashAlgorithmDetails{ + hashAlgoUnknown: {}, + hashAlgoSHA1: { + name: "sha1", + size: sha1.Size, + sum: func(data []byte) Hash { + sum := sha1.Sum(data) + var h Hash + copy(h.data[:], sum[:]) + h.algo = hashAlgoSHA1 + return h + }, + }, + hashAlgoSHA256: { + name: "sha256", + size: sha256.Size, + sum: func(data []byte) Hash { + sum := sha256.Sum256(data) + var h Hash + copy(h.data[:], sum[:]) + h.algo = hashAlgoSHA256 + return h + }, + }, +} + +func (algo hashAlgorithm) info() hashAlgorithmDetails { + return hashAlgorithmTable[algo] +} + +// Size returns the hash size in bytes. +func (algo hashAlgorithm) Size() int { + return algo.info().size } // String returns the canonical name of the hash algorithm. func (algo hashAlgorithm) String() string { - switch algo { - case hashAlgoSHA1: - return "sha1" - case hashAlgoSHA256: - return "sha256" - default: + inf := algo.info() + if inf.name == "" { return "unknown" } + return inf.name +} + +func (algo hashAlgorithm) HexLen() int { + return algo.Size() * 2 +} + +func (algo hashAlgorithm) Sum(data []byte) Hash { + return algo.info().sum(data) } // Hash represents a Git object ID. @@ -67,12 +82,9 @@ type Hash struct { data [maxHashSize]byte } -// hashFunc is a function that computes a hash from input data. -type hashFunc func([]byte) Hash - // String returns a hexadecimal string representation of the hash. func (hash Hash) String() string { - size := hash.algo.size() + size := hash.algo.Size() if size == 0 { return "" } @@ -81,7 +93,7 @@ func (hash Hash) String() string { // Bytes returns a copy of the hash's bytes. func (hash Hash) Bytes() []byte { - size := hash.algo.size() + size := hash.algo.Size() if size == 0 { return nil } @@ -90,5 +102,21 @@ func (hash Hash) Bytes() []byte { // Size returns the hash size. func (hash Hash) Size() int { - return hash.algo.size() + return hash.algo.Size() +} + +var algoByName = map[string]hashAlgorithm{} + +func init() { + for algo, info := range hashAlgorithmTable { + if info.name == "" { + continue + } + algoByName[info.name] = hashAlgorithm(algo) + } +} + +func parseHashAlgorithm(s string) (hashAlgorithm, bool) { + algo, ok := algoByName[s] + return algo, ok } |
