mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-11 10:33:08 -06:00
This DynamoDB store borrows some logic from HttpStore, in that Get, Has and Put requests are dumped into channels that are watched by code in goroutines and batched up to be sent to the backend. A few structs have been factored out of http_store.go and moved to remote_requests.go, where they are enhanced so that DynamoStore can use them as well.
117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package ref
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"hash"
|
|
"io"
|
|
"regexp"
|
|
|
|
"github.com/attic-labs/noms/d"
|
|
)
|
|
|
|
var (
|
|
// In the future we will allow different digest types, so this will get more complicated. For now sha1 is fine.
|
|
pattern = regexp.MustCompile("^sha1-([0-9a-f]{40})$")
|
|
emptyRef = Ref{}
|
|
)
|
|
|
|
type Sha1Digest [sha1.Size]byte
|
|
|
|
type Ref struct {
|
|
// In the future, we will also store the algorithm, and digest will thus probably have to be a slice (because it can vary in size)
|
|
digest Sha1Digest
|
|
}
|
|
|
|
// Digest returns a *copy* of the digest that backs Ref.
|
|
func (r Ref) Digest() Sha1Digest {
|
|
return r.digest
|
|
}
|
|
|
|
func (r Ref) IsEmpty() bool {
|
|
return r.digest == emptyRef.digest
|
|
}
|
|
|
|
func (r Ref) DigestSlice() []byte {
|
|
return r.digest[:]
|
|
}
|
|
|
|
func (r Ref) String() string {
|
|
return fmt.Sprintf("sha1-%s", hex.EncodeToString(r.digest[:]))
|
|
}
|
|
|
|
func New(digest Sha1Digest) Ref {
|
|
return Ref{digest}
|
|
}
|
|
|
|
// NewHash creates a new instance of the hash we use for refs.
|
|
func NewHash() hash.Hash {
|
|
return sha1.New()
|
|
}
|
|
|
|
func FromData(data []byte) Ref {
|
|
h := NewHash()
|
|
_, err := io.Copy(h, bytes.NewReader(data))
|
|
d.Chk.NoError(err)
|
|
return FromHash(h)
|
|
}
|
|
|
|
// FromSlice creates a new Ref backed by data, ensuring that data is an acceptable length.
|
|
func FromSlice(data []byte) Ref {
|
|
d.Chk.Len(data, sha1.Size)
|
|
digest := Sha1Digest{}
|
|
copy(digest[:], data)
|
|
return New(digest)
|
|
}
|
|
|
|
func FromHash(h hash.Hash) Ref {
|
|
d.Chk.Equal(sha1.Size, h.Size())
|
|
digest := Sha1Digest{}
|
|
h.Sum(digest[:0])
|
|
return New(digest)
|
|
}
|
|
|
|
func MaybeParse(s string) (r Ref, ok bool) {
|
|
match := pattern.FindStringSubmatch(s)
|
|
if match == nil {
|
|
return
|
|
}
|
|
|
|
// TODO: The new temp byte array is kinda bummer. Would be better to walk the string and decode each byte into result.digest. But can't find stdlib functions to do that.
|
|
n, err := hex.Decode(r.digest[:], []byte(match[1]))
|
|
d.Chk.NoError(err) // The regexp above should have validated the input
|
|
|
|
// If there was no error, we should have decoded exactly one digest worth of bytes.
|
|
d.Chk.Equal(sha1.Size, n)
|
|
ok = true
|
|
return
|
|
}
|
|
|
|
func Parse(s string) Ref {
|
|
r, ok := MaybeParse(s)
|
|
if !ok {
|
|
d.Exp.Fail(fmt.Sprintf("Cound not parse ref: %s", s))
|
|
}
|
|
return r
|
|
}
|
|
|
|
func (r Ref) Less(other Ref) bool {
|
|
d1, d2 := r.digest, other.digest
|
|
for k := 0; k < len(d1); k++ {
|
|
b1, b2 := d1[k], d2[k]
|
|
if b1 < b2 {
|
|
return true
|
|
} else if b1 > b2 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (r Ref) Greater(other Ref) bool {
|
|
return !r.Less(other) && r != other
|
|
}
|