internal/artifact/source.go (39 lines of code) (raw):

package artifact import ( "fmt" "hash" "io" ) // Source is a binary data source. Sources must be streamed in their entirety before their // checksums can be validated. Sources are closable. It is up to the producer to determine who // is responsible for closing the Source. type Source interface { io.ReadCloser ChecksumVerifier } // ChecksumVerifier verifies the checksum of a data source. type ChecksumVerifier interface { // VerifyChecksum returns true if ExpectedChecksum() is equal to ActualChecksum(). Otherwise // it returns false. If expected and actual are nil, it returns true. VerifyChecksum() bool // ExpectedChecksum returns the expected checksum of the underlying data. ExpectedChecksum() []byte // ActualChecksum returns the actual checksum of underlying data. ActualChecksum() []byte } // WithChecksum creates a checksumVerifier. The digest is used to calculate srcs checksum. // The returned Source should be used to read the artifact contents. func WithChecksum(rc io.ReadCloser, digest hash.Hash, expect []byte) (Source, error) { parsedExpectedChecksum, err := ParseGNUChecksum(expect) if err != nil { return nil, fmt.Errorf("parsing expected checksum: %w", err) } return struct { io.Reader io.Closer ChecksumVerifier }{ Reader: io.TeeReader(rc, digest), Closer: rc, ChecksumVerifier: checksumVerifier{expect: parsedExpectedChecksum, digest: digest}, }, nil } // WithNopChecksum turns rc into a Source that nops when the ChecksumVerifier methods are called. // Both ActualChecksum() and ExpectedChecksum() will return nil. func WithNopChecksum(rc io.ReadCloser) Source { return struct { io.ReadCloser ChecksumVerifier }{ ReadCloser: rc, ChecksumVerifier: nopChecksumVerifier{}, } }