pomerium/internal/hashutil/hashutil.go
2024-11-06 12:31:52 -05:00

206 lines
4.6 KiB
Go

// Package hashutil provides NON-CRYPTOGRAPHIC utility functions for hashing.
//
// http://cyan4973.github.io/xxHash/
//
//nolint:errcheck
package hashutil
import (
"encoding/binary"
"github.com/cespare/xxhash/v2"
"github.com/mitchellh/hashstructure/v2"
)
// MustHash returns the xxhash of an arbitrary value or struct. Returns 0
// on error.
// NOT SUITABLE FOR CRYTOGRAPHIC HASHING.
func MustHash(v any) uint64 {
hash, err := Hash(v)
if err != nil {
hash = 0
}
return hash
}
// Hash returns the xxhash of an arbitrary value or struct.
// NOT SUITABLE FOR CRYTOGRAPHIC HASHING.
func Hash(v any) (uint64, error) {
opts := &hashstructure.HashOptions{
Hasher: xxhash.New(),
}
return hashstructure.Hash(v, hashstructure.FormatV2, opts)
}
type Digest struct {
xxhash.Digest
}
func NewDigest() *Digest {
var d Digest
d.Reset()
return &d
}
// WriteStringWithLen writes the string's length, then its contents to the hash.
func (d *Digest) WriteStringWithLen(s string) {
d.WriteInt32(int32(len(s)))
d.WriteString(s)
}
// WriteStringWithLen writes the byte array's length, then its contents to
// the hash.
func (d *Digest) WriteWithLen(b []byte) {
d.WriteInt32(int32(len(b)))
d.Write(b)
}
// WriteBool writes a single byte (1 or 0) to the hash.
func (d *Digest) WriteBool(b bool) {
if b {
d.Write([]byte{1})
} else {
d.Write([]byte{0})
}
}
// WriteUint32 writes a uint16 to the hash.
func (d *Digest) WriteUint16(t uint16) {
var buf [2]byte
binary.LittleEndian.PutUint16(buf[:], t)
d.Write(buf[:])
}
// WriteUint32 writes a uint32 to the hash.
func (d *Digest) WriteUint32(t uint32) {
var buf [4]byte
binary.LittleEndian.PutUint32(buf[:], t)
d.Write(buf[:])
}
// WriteUint32 writes a uint64 to the hash.
func (d *Digest) WriteUint64(t uint64) {
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], t)
d.Write(buf[:])
}
// WriteInt16 writes an int16 to the hash.
func (d *Digest) WriteInt16(t int16) {
var buf [2]byte
binary.LittleEndian.PutUint16(buf[:], uint16(t))
d.Write(buf[:])
}
// WriteInt32 writes an int32 to the hash.
func (d *Digest) WriteInt32(t int32) {
var buf [4]byte
binary.LittleEndian.PutUint32(buf[:], uint32(t))
d.Write(buf[:])
}
// WriteInt64 writes an int64 to the hash.
func (d *Digest) WriteInt64(t int64) {
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], uint64(t))
d.Write(buf[:])
}
// WriteStringPtr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteStringPtr(t *string) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteString(*t)
}
}
// WriteStringPtr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the string's length and value, if present.
func (d *Digest) WriteStringPtrWithLen(t *string) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteStringWithLen(*t)
}
}
// WriteBoolPtr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteBoolPtr(t *bool) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteBool(*t)
}
}
// WriteUint16Ptr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteUint16Ptr(t *uint16) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteUint16(*t)
}
}
// WriteUint32Ptr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteUint32Ptr(t *uint32) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteUint32(*t)
}
}
// WriteUint64Ptr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteUint64Ptr(t *uint64) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteUint64(*t)
}
}
// WriteInt16Ptr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteInt16Ptr(t *int16) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteInt16(*t)
}
}
// WriteInt32Ptr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteInt32Ptr(t *int32) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteInt32(*t)
}
}
// WriteInt64Ptr writes one byte (1 or 0) indicating whether the pointer is non-nil,
// followed by the value if present.
func (d *Digest) WriteInt64Ptr(t *int64) {
if t == nil {
d.Write([]byte{0})
} else {
d.Write([]byte{1})
d.WriteInt64(*t)
}
}