102 lines
1.3 KiB
Go
102 lines
1.3 KiB
Go
package rewind
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/binary"
|
|
"hash"
|
|
"io"
|
|
"math"
|
|
)
|
|
|
|
type Key interface {
|
|
Size() int
|
|
}
|
|
|
|
type Keyframer interface {
|
|
Capture(reuse Key) Key
|
|
Restore(k Key)
|
|
Hash(h *Hasher)
|
|
}
|
|
|
|
type AfterRestorer interface {
|
|
AfterRestore()
|
|
}
|
|
|
|
type Provider interface {
|
|
Keyframer() Keyframer
|
|
}
|
|
|
|
func Of(v any) (Keyframer, bool) {
|
|
if k, ok := v.(Keyframer); ok {
|
|
return k, true
|
|
}
|
|
if p, ok := v.(Provider); ok {
|
|
if k := p.Keyframer(); k != nil {
|
|
return k, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
type Hasher struct {
|
|
h hash.Hash
|
|
buf [8]byte
|
|
}
|
|
|
|
func NewHasher() *Hasher {
|
|
return &Hasher{h: sha256.New()}
|
|
}
|
|
|
|
func (h *Hasher) Reset() {
|
|
h.h.Reset()
|
|
}
|
|
|
|
func (h *Hasher) U64(v uint64) {
|
|
binary.LittleEndian.PutUint64(h.buf[:], v)
|
|
h.h.Write(h.buf[:])
|
|
}
|
|
|
|
func (h *Hasher) U32(v uint32) {
|
|
h.U64(uint64(v))
|
|
}
|
|
|
|
func (h *Hasher) I64(v int64) {
|
|
h.U64(uint64(v))
|
|
}
|
|
|
|
func (h *Hasher) Int(v int) {
|
|
h.U64(uint64(v))
|
|
}
|
|
|
|
func (h *Hasher) F32(v float32) {
|
|
h.U64(uint64(math.Float32bits(v)))
|
|
}
|
|
|
|
func (h *Hasher) F64(v float64) {
|
|
h.U64(math.Float64bits(v))
|
|
}
|
|
|
|
func (h *Hasher) Bool(v bool) {
|
|
if v {
|
|
h.U64(1)
|
|
return
|
|
}
|
|
h.U64(0)
|
|
}
|
|
|
|
func (h *Hasher) String(s string) {
|
|
h.Int(len(s))
|
|
io.WriteString(h.h, s)
|
|
}
|
|
|
|
func (h *Hasher) Bytes(b []byte) {
|
|
h.Int(len(b))
|
|
h.h.Write(b)
|
|
}
|
|
|
|
func (h *Hasher) Sum() [32]byte {
|
|
var out [32]byte
|
|
h.h.Sum(out[:0])
|
|
return out
|
|
}
|