Skip to content

Commit

Permalink
mod id.Extract to return an error if no valid id is found
Browse files Browse the repository at this point in the history
* add function Factory.QIDFromQIHOT (format)
  • Loading branch information
elv-gilles committed Nov 6, 2023
1 parent 0ea6502 commit e848778
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 12 deletions.
25 changes: 25 additions & 0 deletions format/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ type Factory interface {

// NewMetadataCodec returns the codec for serializing metadata
NewMetadataCodec() codecs.MultiCodec

QIDFromQIHOT(qihot string) (QID, error)
}

// NewFactory creates a new format factory.
Expand Down Expand Up @@ -277,3 +279,26 @@ func (f *factory) NewMetadataCodec() codecs.MultiCodec {
func (f *factory) ParseQSpaceID(s string) (QSpaceID, error) {
return id.QSpace.FromString(s)
}

// QIDFromQIHOT retrieves the content ID in the given hash write token and qid.
// The function expects a content hash, a content write token or a content ID.
func (f *factory) QIDFromQIHOT(qihot string) (QID, error) {
e := errors.Template("QIDFromQIHOT", errors.K.Invalid, "qihot", qihot)
var qid id.ID
qh, err := f.ParseQHash(qihot)
if err != nil {
var qwt QWriteToken
qwt, err = f.ParseQWriteToken(qihot)
if err != nil {
qid, err = f.ParseQID(qihot)
} else {
qid = qwt.QID
}
} else {
qid = qh.ID
}
if err != nil {
return nil, e("reason", "not a qhash, a token or a qid", err)
}
return qid, nil
}
21 changes: 15 additions & 6 deletions format/id/util.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
package id

// Extract parses each of the provided strings as an ID. Empty strings are ignored, parsing errors are returned. The
// first ID that is compatible with the provided target code is returned. If an ID has an embedded ID that matches, it
// is returned.
import (
"strings"

"github.com/eluv-io/errors-go"
)

// Extract parses each of the provided strings as an ID. Empty strings are ignored, parsing errors are returned.
// The first ID that is compatible with the provided target code and is valid is returned. If an ID has an embedded
// valid ID that matches, it is returned.
// If no valid ID is found, an error is returned.
func Extract(target Code, ids ...string) (ID, error) {
for _, candidate := range ids {
if candidate != "" {
cid, err := Parse(candidate)
if err != nil {
return nil, err
}
if cid.Code().IsCompatible(target) {
if cid.Code().IsCompatible(target) && cid.IsValid() {
return cid, nil
}
cid = Decompose(cid).Embedded()
if cid.Code().IsCompatible(target) {
if cid.Code().IsCompatible(target) && cid.IsValid() {
return cid, nil
}
}
}
return nil, nil
return nil, errors.E("Extract", errors.K.Invalid,
"reason", "no valid id found",
"ids", strings.Join(ids, ","))
}
13 changes: 7 additions & 6 deletions format/id/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,29 @@ func TestExtract(t *testing.T) {
want id.ID
wantErr bool
}{
{id.Tenant, nil, nil, false},
{id.Tenant, []string{""}, nil, false},
{id.Tenant, nil, nil, true},
{id.Tenant, []string{""}, nil, true},
{id.Tenant, []string{tid.String()}, tid, false},
{id.Tenant, []string{"", qid.String(), lid.String(), tid.String()}, tid, false},
{id.Tenant, []string{tqid.String()}, tid, false},
{id.Tenant, []string{tlid.String()}, tid, false},
{id.Tenant, []string{einv.String()}, id.NewID(id.Tenant, nil), false},
{id.Tenant, []string{einv2.String()}, id.NewID(id.Tenant, nil), false},
{id.Tenant, []string{einv.String()}, id.NewID(id.Tenant, nil), true},
{id.Tenant, []string{einv2.String()}, id.NewID(id.Tenant, nil), true},
{id.Q, []string{tqid.String()}, tqid.ID(), false},
{id.QLib, []string{tlid.String()}, tlid.ID(), false},
{id.Tenant, []string{"no ID!"}, nil, true},
{id.Tenant, []string{"", qid.String(), "no ID!"}, nil, true},
{id.Tenant, []string{einv3.String()}, id.NewID(id.Tenant, nil), false},
{id.Tenant, []string{einv3.String()}, id.NewID(id.Tenant, nil), true},
}
for i, tt := range tests {
t.Run(fmt.Sprint(tt.target, " ", strings.Join(tt.ids, "|")), func(t *testing.T) {
got, err := id.Extract(tt.target, tt.ids...)
require.Equal(t, tt.want, got, "case %d", i)
if tt.wantErr {
require.Error(t, err, "case %d", i)
} else {
require.Equal(t, tt.want, got, "case %d", i)
require.NoError(t, err, "case %d", i)
require.True(t, got.IsValid(), "case %d", i)
}
})
}
Expand Down

0 comments on commit e848778

Please sign in to comment.