package extraio

import (
	
	
)

// HashReader wraps hash.Hash as an io.Reader. It assumes that the underlying
// hash state does not change after the first Read call.
type HashReader struct {
	h hash.Hash

	buf []byte // mutable
	off int    // mutable
}

// NewStrippedHashReader returns a new io.Reader that reads at most n bytes of
// the given hash function.
func ( hash.Hash,  int64) io.Reader {
	return io.LimitReader(NewHashReader(), )
}

// NewHashReader returns a new reader that reads from the given hash function.
func ( hash.Hash) *HashReader {
	 := make([]byte, 0, .Size())
	return &HashReader{
		h:   ,
		buf: ,
	}
}

// Hash returns the underlying hash function.
func ( *HashReader) () hash.Hash {
	return .h
}

// Reset resets the reader’s state. It does not reset the state of the
// underlying hash function.
func ( *HashReader) () {
	.buf = .buf[:0]
	.off = 0
}

// Read implements the io.Reader interface. It computes the hash on the first
// call and advances through the hash buffer on subsequent calls to Read.
func ( *HashReader) ( []byte) (int, error) {
	if len(.buf) == 0 {
		.buf = .h.Sum(.buf)
	}

	 := cap(.buf)
	if  == .off {
		return 0, io.EOF
	}

	 := copy(, .buf[.off:])
	.off += 

	if  == .off {
		return , io.EOF
	}

	return , nil
}