Skip to content

address some linting issues, and small refactor, performance optimizations #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,14 @@ func RegisterAlgorithm(algorithm Algorithm, implementation CryptoHash) bool {
algorithmsLock.Lock()
defer algorithmsLock.Unlock()

if !algorithmRegexp.MatchString(string(algorithm)) {
panic(fmt.Sprintf("Algorithm %s has a name which does not fit within the allowed grammar", algorithm))
}

if _, ok := algorithms[algorithm]; ok {
return false
}

if !algorithmRegexp.MatchString(string(algorithm)) {
panic(fmt.Sprintf("Algorithm %s has a name which does not fit within the allowed grammar", algorithm))
}

algorithms[algorithm] = implementation
// We can do this since the Digest function below only implements a hex digest. If we open this in the future
// we need to allow for alternative digest algorithms to be implemented and for the user to pass their own
Expand All @@ -156,8 +156,8 @@ func RegisterAlgorithm(algorithm Algorithm, implementation CryptoHash) bool {

// hexDigestRegex can be used to generate a regex for RegisterAlgorithm.
func hexDigestRegex(cryptoHash CryptoHash) *regexp.Regexp {
hexdigestbytes := cryptoHash.Size() * 2
return regexp.MustCompile(fmt.Sprintf("^[a-f0-9]{%d}$", hexdigestbytes))
hexDigestBytes := cryptoHash.Size() * 2
return regexp.MustCompile(fmt.Sprintf("^[a-f0-9]{%d}$", hexDigestBytes))
}

// Available returns true if the digest type is available for use. If this
Expand Down Expand Up @@ -254,20 +254,18 @@ func (a Algorithm) Encode(d []byte) string {

// FromReader returns the digest of the reader using the algorithm.
func (a Algorithm) FromReader(rd io.Reader) (Digest, error) {
digester := a.Digester()

if _, err := io.Copy(digester.Hash(), rd); err != nil {
d := a.Digester()
if _, err := io.Copy(d.Hash(), rd); err != nil {
return "", err
}

return digester.Digest(), nil
return d.Digest(), nil
}

// FromBytes digests the input and returns a Digest.
func (a Algorithm) FromBytes(p []byte) Digest {
digester := a.Digester()

if _, err := digester.Hash().Write(p); err != nil {
d := a.Digester()
if _, err := d.Hash().Write(p); err != nil {
// Writes to a Hash should never fail. None of the existing
// hash implementations in the stdlib or hashes vendored
// here can return errors from Write. Having a panic in this
Expand All @@ -276,7 +274,7 @@ func (a Algorithm) FromBytes(p []byte) Digest {
panic("write to hash function returned error: " + err.Error())
}

return digester.Digest()
return d.Digest()
}

// FromString digests the string input and returns a Digest.
Expand Down
3 changes: 2 additions & 1 deletion algorithm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"bytes"
"crypto"
"crypto/rand"
"errors"
"flag"
"fmt"
"strings"
Expand Down Expand Up @@ -56,7 +57,7 @@ func TestFlagInterface(t *testing.T) {
} {
t.Run(testcase.Name, func(t *testing.T) {
alg = Canonical
if err := flagSet.Parse(testcase.Args); err != testcase.Err {
if err := flagSet.Parse(testcase.Args); !errors.Is(err, testcase.Err) {
if testcase.Err == nil {
t.Fatal("unexpected error", err)
}
Expand Down
13 changes: 7 additions & 6 deletions digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package digest

import (
"errors"
"fmt"
"hash"
"io"
Expand Down Expand Up @@ -46,19 +47,19 @@ func NewDigest(alg Algorithm, h hash.Hash) Digest {
// functions. This is also useful for rebuilding digests from binary
// serializations.
func NewDigestFromBytes(alg Algorithm, p []byte) Digest {
return NewDigestFromEncoded(alg, alg.Encode(p))
return Digest(string(alg) + ":" + alg.Encode(p))
}

// NewDigestFromHex returns a Digest from alg and the hex encoded digest.
//
// Deprecated: use [NewDigestFromEncoded] instead.
func NewDigestFromHex(alg, hex string) Digest {
return NewDigestFromEncoded(Algorithm(alg), hex)
return Digest(alg + ":" + hex)
}

// NewDigestFromEncoded returns a Digest from alg and the encoded digest.
func NewDigestFromEncoded(alg Algorithm, encoded string) Digest {
return Digest(fmt.Sprintf("%s:%s", alg, encoded))
return Digest(string(alg) + ":" + encoded)
}

// DigestRegexp matches valid digest types.
Expand All @@ -69,13 +70,13 @@ var DigestRegexpAnchored = regexp.MustCompile(`^` + DigestRegexp.String() + `$`)

var (
// ErrDigestInvalidFormat returned when digest format invalid.
ErrDigestInvalidFormat = fmt.Errorf("invalid checksum digest format")
ErrDigestInvalidFormat = errors.New("invalid checksum digest format")

// ErrDigestInvalidLength returned when digest has invalid length.
ErrDigestInvalidLength = fmt.Errorf("invalid checksum digest length")
ErrDigestInvalidLength = errors.New("invalid checksum digest length")

// ErrDigestUnsupported returned when the digest algorithm is unsupported.
ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm")
ErrDigestUnsupported = errors.New("unsupported digest algorithm")
)

// Parse parses s and returns the validated digest object. An error will
Expand Down
19 changes: 19 additions & 0 deletions digest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package digest_test

import (
"crypto/sha256"
"testing"

"github.com/opencontainers/go-digest"
Expand Down Expand Up @@ -118,3 +119,21 @@ func TestParseDigest(t *testing.T) {
})
}
}

func BenchmarkNewDigestFromEncoded(b *testing.B) {
b.ReportAllocs()

for i := 0; i < b.N; i++ {
_ = digest.NewDigestFromEncoded("sha256", "e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b")
}
}

func BenchmarkNewDigestFromBytes(b *testing.B) {
s := sha256.Sum256([]byte("hello world"))

b.ReportAllocs()

for i := 0; i < b.N; i++ {
_ = digest.NewDigestFromBytes("sha256", s[:])
}
}
4 changes: 2 additions & 2 deletions digestset/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"strings"
"sync"

digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/go-digest"
)

var (
Expand Down Expand Up @@ -93,7 +93,7 @@ func (dst *Set) Lookup(d string) (digest.Digest, error) {
hex string
)
dgst, err := digest.Parse(d)
if err == digest.ErrDigestInvalidFormat {
if errors.Is(err, digest.ErrDigestInvalidFormat) {
hex = d
searchFunc = func(i int) bool {
return dst.entries[i].val >= d
Expand Down
6 changes: 5 additions & 1 deletion digestset/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"math/rand"
"testing"

digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/go-digest"
)

func assertEqualDigests(t *testing.T, d1, d2 digest.Digest) {
Expand Down Expand Up @@ -257,6 +257,7 @@ func createDigests(count int) ([]digest.Digest, error) {
}

func benchAddNTable(b *testing.B, n int) {
b.ReportAllocs()
digests, err := createDigests(n)
if err != nil {
b.Fatal(err)
Expand All @@ -273,6 +274,7 @@ func benchAddNTable(b *testing.B, n int) {
}

func benchLookupNTable(b *testing.B, n int, shortLen int) {
b.ReportAllocs()
digests, err := createDigests(n)
if err != nil {
b.Fatal(err)
Expand All @@ -297,6 +299,7 @@ func benchLookupNTable(b *testing.B, n int, shortLen int) {
}

func benchRemoveNTable(b *testing.B, n int) {
b.ReportAllocs()
digests, err := createDigests(n)
if err != nil {
b.Fatal(err)
Expand All @@ -320,6 +323,7 @@ func benchRemoveNTable(b *testing.B, n int) {
}

func benchShortCodeNTable(b *testing.B, n int, shortLen int) {
b.ReportAllocs()
digests, err := createDigests(n)
if err != nil {
b.Fatal(err)
Expand Down
37 changes: 19 additions & 18 deletions testdigest/testdigest.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// testdigest is a separate package, because it has some testing utilities in it that may be useful
// to other internal Algorithm implementors.
// Package testdigest is a separate package, because it has some testing
// utilities that may be useful to other internal Algorithm implementors.
//
// It is not a stable interface and not meant for consumption outside of digest developers.

// It is not a stable interface and not meant for consumption outside of
// digest developers.
package testdigest

import (
"errors"
"testing"

pkgdigest "github.com/opencontainers/go-digest"
"github.com/opencontainers/go-digest"
)

type TestCase struct {
Expand All @@ -31,41 +32,41 @@ type TestCase struct {
// If err is non-nil, then the parsing of Input is expected to return this error
Err error
// Algorithm should be an available or registered algorithm
Algorithm pkgdigest.Algorithm
Algorithm digest.Algorithm
// Encoded is the the encoded portion of the digest to expect, for example e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b
Encoded string
}

func RunTestCase(t *testing.T, testcase TestCase) {
digest, err := pkgdigest.Parse(testcase.Input)
if err != testcase.Err {
dgst, err := digest.Parse(testcase.Input)
if !errors.Is(err, testcase.Err) {
t.Fatalf("error differed from expected while parsing %q: %v != %v", testcase.Input, err, testcase.Err)
}

if testcase.Err != nil {
return
}

if digest.Algorithm() != testcase.Algorithm {
t.Fatalf("incorrect Algorithm for parsed digest: %q != %q", digest.Algorithm(), testcase.Algorithm)
if dgst.Algorithm() != testcase.Algorithm {
t.Fatalf("incorrect Algorithm for parsed digest: %q != %q", dgst.Algorithm(), testcase.Algorithm)
}

if digest.Encoded() != testcase.Encoded {
t.Fatalf("incorrect hex for parsed digest: %q != %q", digest.Encoded(), testcase.Encoded)
if dgst.Encoded() != testcase.Encoded {
t.Fatalf("incorrect hex for parsed digest: %q != %q", dgst.Encoded(), testcase.Encoded)
}

// Parse string return value and check equality
newParsed, err := pkgdigest.Parse(digest.String())
newParsed, err := digest.Parse(dgst.String())
if err != nil {
t.Fatalf("unexpected error parsing Input %q: %v", testcase.Input, err)
}

if newParsed != digest {
t.Fatalf("expected equal: %q != %q", newParsed, digest)
if newParsed != dgst {
t.Fatalf("expected equal: %q != %q", newParsed, dgst)
}

newFromHex := pkgdigest.NewDigestFromEncoded(newParsed.Algorithm(), newParsed.Encoded())
if newFromHex != digest {
t.Fatalf("%v != %v", newFromHex, digest)
newFromHex := digest.NewDigestFromEncoded(newParsed.Algorithm(), newParsed.Encoded())
if newFromHex != dgst {
t.Fatalf("%v != %v", newFromHex, dgst)
}
}
Loading