tokidoki/storage/etag.go
Conrad Hoffmann 665b206709 storage: streamline ETag calculation
This commit introduces some helpers so that ETags can be calculated at
the same time that files get read or written. Besides looking nicer, it
should also help reduce lock contention around file access, as files do
not need to be opened twice anymore.
2024-11-07 17:55:56 +01:00

58 lines
1.2 KiB
Go

package storage
import (
"crypto/sha1"
"encoding/base64"
"hash"
"io"
)
type ETagWriter struct {
io.Writer
output io.Writer
csum hash.Hash
}
// NewETagWriter creates a new io.Writer that pipes writes to the provided
// output while also calculating the contents ETag.
func NewETagWriter(output io.Writer) *ETagWriter {
csum := sha1.New()
return &ETagWriter{
output: io.MultiWriter(output, csum),
csum: csum,
}
}
func (e *ETagWriter) Write(p []byte) (n int, err error) {
return e.output.Write(p)
}
func (e *ETagWriter) ETag() string {
csum := e.csum.Sum(nil)
return base64.StdEncoding.EncodeToString(csum[:])
}
type ETagReader struct {
io.Reader
input io.Reader
csum hash.Hash
}
// NewETagReader creates a new io.Reader that pipes reads from the provided
// input while also calculating the contents ETag.
func NewETagReader(input io.Reader) *ETagReader {
csum := sha1.New()
return &ETagReader{
input: io.TeeReader(input, csum),
csum: csum,
}
}
func (e *ETagReader) Read(p []byte) (n int, err error) {
return e.input.Read(p)
}
func (e *ETagReader) ETag() string {
csum := e.csum.Sum(nil)
return base64.StdEncoding.EncodeToString(csum[:])
}