Skip to content

Commit

Permalink
syntax: more ergonomic sub-field accessors
Browse files Browse the repository at this point in the history
  • Loading branch information
bnewbold committed Sep 15, 2023
1 parent 898befd commit 4ef5ee5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 26 deletions.
52 changes: 33 additions & 19 deletions atproto/syntax/aturi.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,23 @@ func ParseATURI(raw string) (ATURI, error) {
return ATURI(raw), nil
}

func (n ATURI) Authority() (*AtIdentifier, error) {
// Every valid ATURI has a valid AtIdentifier in the authority position.
//
// If this ATURI is malformed, returns empty
func (n ATURI) Authority() AtIdentifier {
parts := strings.SplitN(string(n), "/", 4)
if len(parts) < 3 {
// something has gone wrong (would not validate)
return nil, fmt.Errorf("AT-URI has no authority segment (invalid)")
return AtIdentifier{}
}
atid, err := ParseAtIdentifier(parts[2])
if err != nil {
return AtIdentifier{}
}
return ParseAtIdentifier(parts[2])
return *atid
}

// Returns path segment, without leading slash, as would be used in an atproto repository key
// Returns path segment, without leading slash, as would be used in an atproto repository key. Or empty string if there is no path.
func (n ATURI) Path() string {
parts := strings.SplitN(string(n), "/", 5)
if len(parts) < 3 {
Expand All @@ -65,38 +72,45 @@ func (n ATURI) Path() string {
return parts[2] + "/" + parts[3]
}

func (n ATURI) Collection() (NSID, error) {
// Returns a valid NSID if there is one in the appropriate part of the path, otherwise empty.
func (n ATURI) Collection() NSID {
parts := strings.SplitN(string(n), "/", 5)
if len(parts) < 4 {
// something has gone wrong (would not validate)
return NSID(""), fmt.Errorf("AT-URI has no collection segment")
return NSID("")
}
nsid, err := ParseNSID(parts[3])
if err != nil {
return NSID("")
}
// re-parsing is safest
return ParseNSID(parts[3])
return nsid
}

func (n ATURI) RecordKey() (RecordKey, error) {
func (n ATURI) RecordKey() RecordKey {
parts := strings.SplitN(string(n), "/", 6)
if len(parts) < 5 {
// something has gone wrong (would not validate)
return RecordKey(""), fmt.Errorf("AT-URI has no record key segment")
return RecordKey("")
}
// re-parsing is safest
return ParseRecordKey(parts[4])
rkey, err := ParseRecordKey(parts[4])
if err != nil {
return RecordKey("")
}
return rkey
}

func (n ATURI) Normalize() ATURI {
auth, err := n.Authority()
if err != nil {
// invalid AT-URI
auth := n.Authority()
if auth.Inner == nil {
// invalid AT-URI; return the current value (!)
return n
}
coll, err := n.Collection()
if err != nil {
coll := n.Collection()
if coll == NSID("") {
return ATURI("at://" + auth.Normalize().String())
}
rkey, err := n.RecordKey()
if err != nil {
rkey := n.RecordKey()
if rkey == RecordKey("") {
return ATURI("at://" + auth.Normalize().String() + "/" + coll.String())
}
return ATURI("at://" + auth.Normalize().String() + "/" + coll.Normalize().String() + "/" + rkey.String())
Expand Down
13 changes: 6 additions & 7 deletions atproto/syntax/aturi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,11 @@ func TestATURIParts(t *testing.T) {
for _, parts := range testVec {
uri, err := ParseATURI(parts[0])
assert.NoError(err)
auth, _ := uri.Authority()
auth := uri.Authority()
assert.Equal(parts[1], auth.String())
col, _ := uri.Collection()
col := uri.Collection()
assert.Equal(parts[2], col.String())
rkey, _ := uri.RecordKey()
assert.NoError(err)
rkey := uri.RecordKey()
assert.Equal(parts[3], rkey.String())
}

Expand All @@ -89,9 +88,9 @@ func TestATURINormalize(t *testing.T) {
func TestATURINoPanic(t *testing.T) {
for _, s := range []string{"", ".", "at://", "at:///", "at://e.com", "at://e.com/", "at://e.com//"} {
bad := ATURI(s)
_, _ = bad.Authority()
_, _ = bad.Collection()
_, _ = bad.RecordKey()
_ = bad.Authority()
_ = bad.Collection()
_ = bad.RecordKey()
_ = bad.Normalize()
_ = bad.String()
}
Expand Down

0 comments on commit 4ef5ee5

Please sign in to comment.