storj.io/uplink@v1.13.0/private/etag/reader.go (about)

     1  // Copyright (C) 2021 Storj Labs, Inc.
     2  // See LICENSE for copying information.
     3  
     4  package etag
     5  
     6  import (
     7  	"hash"
     8  	"io"
     9  
    10  	"github.com/zeebo/errs"
    11  )
    12  
    13  // Reader that calculates ETag from content.
    14  //
    15  // CurrentETag returns the ETag calculated from the content that is already read.
    16  type Reader interface {
    17  	io.Reader
    18  	CurrentETag() []byte
    19  }
    20  
    21  // HashReader implements the etag.Reader interface by reading from an io.Reader
    22  // and calculating the ETag with a hash.Hash.
    23  type HashReader struct {
    24  	io.Reader
    25  	h hash.Hash
    26  }
    27  
    28  // NewHashReader returns a new HashReader reading from r and calculating the ETag with h.
    29  func NewHashReader(r io.Reader, h hash.Hash) *HashReader {
    30  	return &HashReader{
    31  		Reader: r,
    32  		h:      h,
    33  	}
    34  }
    35  
    36  func (r *HashReader) Read(b []byte) (n int, err error) {
    37  	n, err = r.Reader.Read(b)
    38  	_, hashErr := r.h.Write(b[:n])
    39  	return n, errs.Combine(err, hashErr)
    40  }
    41  
    42  // CurrentETag returns the ETag for the content that has already been read from
    43  // the reader.
    44  func (r *HashReader) CurrentETag() []byte {
    45  	return r.h.Sum(nil)
    46  }