package backend import ( "hash" "io" ) type HashAppendReader struct { r io.Reader h hash.Hash sum []byte closed bool } func NewHashAppendReader(r io.Reader, h hash.Hash) *HashAppendReader { return &HashAppendReader{ h: h, r: io.TeeReader(r, h), sum: make([]byte, 0, h.Size()), } } func (h *HashAppendReader) Read(p []byte) (n int, err error) { if !h.closed { n, err = h.r.Read(p) if err == io.EOF { h.closed = true h.sum = h.h.Sum(h.sum) } else if err != nil { return } } if h.closed { // output hash r := len(p) - n if r > 0 { c := copy(p[n:], h.sum) h.sum = h.sum[c:] n += c err = nil } if len(h.sum) == 0 { err = io.EOF } } return } type HashingReader struct { r io.Reader h hash.Hash } func NewHashingReader(r io.Reader, h hash.Hash) *HashingReader { return &HashingReader{ h: h, r: io.TeeReader(r, h), } } func (h *HashingReader) Read(p []byte) (int, error) { return h.r.Read(p) } func (h *HashingReader) Sum(d []byte) []byte { return h.h.Sum(d) }