util/md5.go

164 lines
2.9 KiB
Go

package util
import (
"crypto/md5"
"encoding/hex"
"errors"
"hash"
"io"
"os"
"path/filepath"
"strings"
)
const MD5ResultLength = 16
type MD5Result struct {
result [MD5ResultLength]byte
err error
}
func (m *MD5Result) Array() [MD5ResultLength]byte {
if m.err != nil {
return [MD5ResultLength]byte{}
}
return m.result
}
func (m *MD5Result) Slice() []byte {
if m.err != nil {
return []byte{}
}
return m.result[:]
}
func (m *MD5Result) Upper() string {
if m.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(m.result[:]))
}
func (m *MD5Result) Lower() string {
if m.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(m.result[:]))
}
func (m *MD5Result) Error() error {
return m.err
}
func NewMD5Result(result []byte, err error) *MD5Result {
res := &MD5Result{
result: [MD5ResultLength]byte{},
err: err,
}
copy(res.result[:], result)
return res
}
type MD5 struct{}
func NewMD5() *MD5 {
return &MD5{}
}
func (m *MD5) FromReader(r io.Reader) *MD5Result {
ha := md5.New()
if _, err := io.Copy(ha, r); err != nil {
return NewMD5Result(nil, err)
}
hashInBytes := ha.Sum(nil)
if len(hashInBytes) != MD5ResultLength {
return NewMD5Result(nil, errors.New("wrong length"))
}
return NewMD5Result(hashInBytes, nil)
}
func (m *MD5) FromFile(filename string) *MD5Result {
file, err := os.Open(filepath.Clean(filename))
if err != nil {
return NewMD5Result(nil, err)
}
defer func() {
_ = file.Close()
}()
return m.FromReader(file)
}
func (m *MD5) FromReaderChunk(r io.Reader, chunksize int) *MD5Result {
buf := make([]byte, chunksize)
m5 := md5.New()
var n int
var err error
for {
n, err = r.Read(buf)
if err != nil {
if err != io.EOF {
return NewMD5Result(nil, err)
}
if n > 0 {
_, err = m5.Write(buf[:n])
if err != nil {
return NewMD5Result(nil, err)
}
}
break
}
_, err = m5.Write(buf[:n])
if err != nil {
return NewMD5Result(nil, err)
}
}
return NewMD5Result(m5.Sum(nil), nil)
}
func (m *MD5) FromFileChunk(filename string, chunksize int) *MD5Result {
file, err := os.Open(filepath.Clean(filename))
if err != nil {
return NewMD5Result(nil, err)
}
defer func() {
_ = file.Close()
}()
return m.FromReaderChunk(file, chunksize)
}
func (m *MD5) FromBytes(b []byte) *MD5Result {
res := md5.Sum(b)
return NewMD5Result(res[:], nil)
}
func (m *MD5) FromString(str string) *MD5Result {
res := md5.Sum([]byte(str))
return NewMD5Result(res[:], nil)
}
type MD5Pip struct {
md5 hash.Hash
}
func NewMD5Pip() *MD5Pip {
return &MD5Pip{md5: md5.New()}
}
func (m *MD5Pip) Write(data []byte) (n int, err error) {
return m.md5.Write(data)
}
func (m *MD5Pip) WriteBytes(data []byte) error {
_, err := m.Write(data)
return err
}
func (m *MD5Pip) WriteString(data string) error {
_, err := m.Write([]byte(data))
return err
}
func (m *MD5Pip) Result() *MD5Result {
return NewMD5Result(m.md5.Sum(nil), nil)
}