Skip to content

Commit

Permalink
Create a CID encoder that optionally upgrades a CIDv0 to CIDv1
Browse files Browse the repository at this point in the history
  • Loading branch information
kevina committed Jan 7, 2019
1 parent 4bb0ce1 commit d22951b
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
1 change: 1 addition & 0 deletions cid-fmt/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ func TestBadCidConv(t *testing.T) {
t.Fatal("expected failure")
}
}

59 changes: 59 additions & 0 deletions cidenc/encoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cidenc

import (
cid "github.com/ipfs/go-cid"
mbase "github.com/multiformats/go-multibase"
)

// Encoder is a basic Encoder that will encode Cid's using a specifed
// base and optionally upgrade a CIDv0 to CIDv1
type Encoder struct {
Base mbase.Encoder // The multibase to use
Upgrade bool // If true upgrade CIDv0 to CIDv1 when encoding
}

// Default return a new default encoder
func Default() Encoder {
return Encoder{Base: mbase.MustNewEncoder(mbase.Base58BTC)}
}

// Encode encoded the cid using the parameters of the Encoder
func (enc Encoder) Encode(c cid.Cid) string {
if enc.Upgrade && c.Version() == 0 {
c = cid.NewCidV1(c.Type(), c.Hash())
}
return c.Encode(enc.Base)
}

// Recode reencodes the cid string to match the parameters of the
// encoder
func (enc Encoder) Recode(v string) (string, error) {
skip, err := enc.noopRecode(v)
if skip || err != nil {
return v, err
}

c, err := cid.Decode(v)
if err != nil {
return v, err
}

return enc.Encode(c), nil
}

func (enc Encoder) noopRecode(v string) (bool, error) {
if len(v) < 2 {
return false, cid.ErrCidTooShort
}
ver := cidVer(v)
skip := ver == 0 && !enc.Upgrade || ver == 1 && v[0] == byte(enc.Base.Encoding())
return skip, nil
}

func cidVer(v string) int {
if len(v) == 46 && v[:2] == "Qm" {
return 0
} else {
return 1
}
}
62 changes: 62 additions & 0 deletions cidenc/encoder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package cidenc

import (
"testing"

cid "github.com/ipfs/go-cid"
mbase "github.com/multiformats/go-multibase"
)

func TestCidEncoder(t *testing.T) {
cidv0str := "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"
cidv1str := "zdj7Wkkhxcu2rsiN6GUyHCLsSLL47kdUNfjbFqBUUhMFTZKBi"
cidb32str := "bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku"
cidv0, _ := cid.Decode(cidv0str)
cidv1, _ := cid.Decode(cidv1str)

testEncode := func(enc Encoder, cid cid.Cid, expect string) {
actual := enc.Encode(cid)
if actual != expect {
t.Errorf("%+v.Encode(%s): expected %s but got %s", enc, cid, expect, actual)
}
}

testRecode := func(enc Encoder, cid string, expect string) {
actual, err := enc.Recode(cid)
if err != nil {
t.Errorf("%+v.Recode(%s): %s", enc, cid, err)
return
}
if actual != expect {
t.Errorf("%+v.Recode(%s): expected %s but got %s", enc, cid, expect, actual)
}
}

enc := Encoder{Base: mbase.MustNewEncoder(mbase.Base58BTC), Upgrade: false}
testEncode(enc, cidv0, cidv0str)
testEncode(enc, cidv1, cidv1str)
testRecode(enc, cidv0str, cidv0str)
testRecode(enc, cidv1str, cidv1str)
testRecode(enc, cidb32str, cidv1str)

enc = Encoder{Base: mbase.MustNewEncoder(mbase.Base58BTC), Upgrade: true}
testEncode(enc, cidv0, cidv1str)
testEncode(enc, cidv1, cidv1str)
testRecode(enc, cidv0str, cidv1str)
testRecode(enc, cidv1str, cidv1str)
testRecode(enc, cidb32str, cidv1str)

enc = Encoder{Base: mbase.MustNewEncoder(mbase.Base32), Upgrade: false}
testEncode(enc, cidv0, cidv0str)
testEncode(enc, cidv1, cidb32str)
testRecode(enc, cidv0str, cidv0str)
testRecode(enc, cidv1str, cidb32str)
testRecode(enc, cidb32str, cidb32str)

enc = Encoder{Base: mbase.MustNewEncoder(mbase.Base32), Upgrade: true}
testEncode(enc, cidv0, cidb32str)
testEncode(enc, cidv1, cidb32str)
testRecode(enc, cidv0str, cidb32str)
testRecode(enc, cidv1str, cidb32str)
testRecode(enc, cidb32str, cidb32str)
}

0 comments on commit d22951b

Please sign in to comment.