diff --git a/path.go b/path.go index e70d963..c081ada 100644 --- a/path.go +++ b/path.go @@ -30,6 +30,24 @@ func FromCid(c cid.Cid) Path { return Path("/ipfs/" + c.String()) } +// ToCid attempts to convert the Path to a CID. This should always work if +// the path was created from ParsePath. +func (p Path) ToCid() (cid.Cid, error) { + parts := strings.Split(p.String(), "/") + if len(parts) < 3 || parts[2] == "" { + return cid.Undef, &pathError{fmt.Errorf("not enough path components"), p.String()} + } + + switch parts[1] { + // TODO: Silently allowing IPNS though ParsePath doesn't validate the CID + // in that case. + case "ipfs", "ipld", "ipns": + return decodeCid(parts[2]) + default: + return cid.Undef, &pathError{fmt.Errorf("invalid namespace %s to extract CID (/ipfs/ or /ipld/ expected)", parts[1]), p.String()} + } +} + // Segments returns the different elements of a path // (elements are delimited by a /). func (p Path) Segments() []string { diff --git a/path_test.go b/path_test.go index 2b26a56..2e865e8 100644 --- a/path_test.go +++ b/path_test.go @@ -30,11 +30,17 @@ func TestPathParsing(t *testing.T) { } for p, expected := range cases { - _, err := ParsePath(p) + p, err := ParsePath(p) valid := err == nil if valid != expected { t.Fatalf("expected %s to have valid == %t", p, expected) } + if valid { + _, err := p.ToCid() + if err != nil { + t.Fatalf("ToCid(): failed to extract CID from valid path: %s", err) + } + } } }