diff options
| -rw-r--r-- | objectid/algorithms.go | 127 | ||||
| -rw-r--r-- | objectid/errors.go | 10 | ||||
| -rw-r--r-- | objectid/objectid.go | 133 |
3 files changed, 139 insertions, 131 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] +} diff --git a/objectid/errors.go b/objectid/errors.go new file mode 100644 index 00000000..8e604c44 --- /dev/null +++ b/objectid/errors.go @@ -0,0 +1,10 @@ +package objectid + +import "errors" + +var ( + // ErrInvalidAlgorithm indicates an unsupported object ID algorithm. + ErrInvalidAlgorithm = errors.New("objectid: invalid algorithm") + // ErrInvalidObjectID indicates malformed object ID data. + ErrInvalidObjectID = errors.New("objectid: invalid object id") +) diff --git a/objectid/objectid.go b/objectid/objectid.go index c1ebfb2c..df56b2d8 100644 --- a/objectid/objectid.go +++ b/objectid/objectid.go @@ -2,141 +2,12 @@ package objectid import ( - "crypto/sha1" //#nosec G505 - "crypto/sha256" + //#nosec G505 + "encoding/hex" - "errors" "fmt" - "hash" -) - -var ( - // ErrInvalidAlgorithm indicates an unsupported object ID algorithm. - ErrInvalidAlgorithm = errors.New("objectid: invalid algorithm") - // ErrInvalidObjectID indicates malformed object ID data. - ErrInvalidObjectID = errors.New("objectid: invalid object id") ) -// 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] -} - // ObjectID represents a Git object ID. // //nolint:recvcheck |
