add 'Prefix' object and some more helper routines

This commit is contained in:
Jeromy
2016-10-08 21:17:59 -07:00
parent 6c7d9e3de2
commit 961f0fe7a8
3 changed files with 114 additions and 1 deletions

73
cid.go
View File

@@ -174,3 +174,76 @@ func (c *Cid) Loggable() map[string]interface{} {
"cid": c,
}
}
func (c *Cid) Prefix() Prefix {
dec, _ := mh.Decode(c.hash) // assuming we got a valid multiaddr, this will not error
return Prefix{
MhType: dec.Code,
MhLength: dec.Length,
Version: c.version,
Codec: c.codec,
}
}
// Prefix represents all the metadata of a cid, minus any actual content information
type Prefix struct {
Version uint64
Codec uint64
MhType int
MhLength int
}
func (p Prefix) Sum(data []byte) (*Cid, error) {
hash, err := mh.Sum(data, p.MhType, p.MhLength)
if err != nil {
return nil, err
}
switch p.Version {
case 0:
return NewCidV0(hash), nil
case 1:
return NewCidV1(p.Codec, hash), nil
default:
return nil, fmt.Errorf("invalid cid version")
}
}
func (p Prefix) Bytes() []byte {
buf := make([]byte, 16)
n := binary.PutUvarint(buf, p.Version)
n += binary.PutUvarint(buf[n:], p.Codec)
n += binary.PutUvarint(buf[n:], uint64(p.MhType))
n += binary.PutUvarint(buf[n:], uint64(p.MhLength))
return buf[:n]
}
func PrefixFromBytes(buf []byte) (Prefix, error) {
r := bytes.NewReader(buf)
vers, err := binary.ReadUvarint(r)
if err != nil {
return Prefix{}, err
}
codec, err := binary.ReadUvarint(r)
if err != nil {
return Prefix{}, err
}
mhtype, err := binary.ReadUvarint(r)
if err != nil {
return Prefix{}, err
}
mhlen, err := binary.ReadUvarint(r)
if err != nil {
return Prefix{}, err
}
return Prefix{
Version: vers,
Codec: codec,
MhType: int(mhtype),
MhLength: int(mhlen),
}, nil
}

View File

@@ -79,3 +79,32 @@ func TestV0ErrorCases(t *testing.T) {
t.Fatal("should have failed to decode that ref")
}
}
func TestPrefixRoundtrip(t *testing.T) {
data := []byte("this is some test content")
hash, _ := mh.Sum(data, mh.SHA2_256, -1)
c := NewCidV1(CBOR, hash)
pref := c.Prefix()
c2, err := pref.Sum(data)
if err != nil {
t.Fatal(err)
}
if !c.Equals(c2) {
t.Fatal("output didnt match original")
}
pb := pref.Bytes()
pref2, err := PrefixFromBytes(pb)
if err != nil {
t.Fatal(err)
}
if pref.Version != pref2.Version || pref.Codec != pref2.Codec ||
pref.MhType != pref2.MhType || pref.MhLength != pref2.MhLength {
t.Fatal("input prefix didnt match output")
}
}

13
set.go
View File

@@ -26,7 +26,7 @@ func (s *Set) Len() int {
}
func (s *Set) Keys() []*Cid {
var out []*Cid
out := make([]*Cid, 0, len(s.set))
for k, _ := range s.set {
c, _ := Cast([]byte(k))
out = append(out, c)
@@ -42,3 +42,14 @@ func (s *Set) Visit(c *Cid) bool {
return false
}
func (s *Set) ForEach(f func(c *Cid) error) error {
for cs, _ := range s.set {
c, _ := Cast([]byte(cs))
err := f(c)
if err != nil {
return err
}
}
return nil
}