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 }