Skip to content

Commit

Permalink
feat: implement the Stringer interface for DID
Browse files Browse the repository at this point in the history
  • Loading branch information
mrinalwadhwa committed Nov 8, 2018
1 parent ce5ca44 commit cdf8b26
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
45 changes: 45 additions & 0 deletions did.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,51 @@ type parser struct {
// a step in the parser state machine that returns the next step
type parserStep func() parserStep

// String encodes a DID struct into a valid DID string.
func (d *DID) String() string {
var buf strings.Builder

// write the did: prefix
buf.WriteString("did:") // nolint, returned error is always nil

if d.Method != "" {
// write method followed by a `:`
buf.WriteString(d.Method) // nolint, returned error is always nil
buf.WriteByte(':') // nolint, returned error is always nil
} else {
// if there is no Method, return an empty string
return ""
}

if d.ID != "" {
buf.WriteString(d.ID) // nolint, returned error is always nil
} else if len(d.IDStrings) > 0 {
// join IDStrings with a colon to make the ID
buf.WriteString(strings.Join(d.IDStrings[:], ":")) // nolint, returned error is always nil
} else {
// if there is no ID, return an empty string
return ""
}

if d.Path != "" {
// write a leading / and then Path
buf.WriteByte('/') // nolint, returned error is always nil
buf.WriteString(d.Path) // nolint, returned error is always nil
} else if len(d.PathSegments) > 0 {
// write a leading / and then PathSegments joined with / between them
buf.WriteByte('/') // nolint, returned error is always nil
buf.WriteString(strings.Join(d.PathSegments[:], "/")) // nolint, returned error is always nil
} else {
// add fragment only when there is no path
if d.Fragment != "" {
buf.WriteByte('#') // nolint, returned error is always nil
buf.WriteString(d.Fragment) // nolint, returned error is always nil
}
}

return buf.String()
}

// Parse parses the input string into a DID structure.
func Parse(input string) (*DID, error) {
// intialize the parser state
Expand Down
85 changes: 85 additions & 0 deletions did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,91 @@ import (
"testing"
)

// nolint
func TestString(t *testing.T) {

t.Run("assembles a DID", func(t *testing.T) {
d := &DID{Method: "example", ID: "123"}
output := d.String()
expected := "did:example:123"
if output != expected {
t.Errorf("output: %s, expected: %s", output, expected)
}
})

t.Run("assembles a DID from IDStrings", func(t *testing.T) {
d := &DID{Method: "example", IDStrings: []string{"123", "456"}}
output := d.String()
expected := "did:example:123:456"
if output != expected {
t.Errorf("output: %s, expected: %s", output, expected)
}
})

t.Run("returns empty string if no method", func(t *testing.T) {
d := &DID{ID: "123"}
output := d.String()
expected := ""
if output != expected {
t.Errorf("output: %s, expected: empty string", output)
}
})

t.Run("returns empty string in no ID or IDStrings", func(t *testing.T) {
d := &DID{Method: "example"}
output := d.String()
expected := ""
if output != expected {
t.Errorf("output: %s, expected: empty string", output)
}
})

t.Run("includes Path", func(t *testing.T) {
d := &DID{Method: "example", ID: "123", Path: "a/b"}
output := d.String()
expected := "did:example:123/a/b"
if output != expected {
t.Errorf("output: %s, expected: %s", output, expected)
}
})

t.Run("includes Path assembled from PathSegements", func(t *testing.T) {
d := &DID{Method: "example", ID: "123", PathSegments: []string{"a", "b"}}
output := d.String()
expected := "did:example:123/a/b"
if output != expected {
t.Errorf("output: %s, expected: %s", output, expected)
}
})

t.Run("includes Fragment", func(t *testing.T) {
d := &DID{Method: "example", ID: "123", Fragment: "00000"}
output := d.String()
expected := "did:example:123#00000"
if output != expected {
t.Errorf("output: %s, expected: %s", output, expected)
}
})

t.Run("does not include Fragment if Path is present", func(t *testing.T) {
d := &DID{Method: "example", ID: "123", Path: "a/b", Fragment: "00000"}
output := d.String()
expected := "did:example:123/a/b"
if output != expected {
t.Errorf("output: %s, expected: %s", output, expected)
}
})

t.Run("does not include Fragment if PathSegments is present", func(t *testing.T) {
d := &DID{Method: "example", ID: "123", PathSegments: []string{"a", "b"}, Fragment: "00000"}
output := d.String()
expected := "did:example:123/a/b"
if output != expected {
t.Errorf("output: %s, expected: %s", output, expected)
}
})
}

// nolint
func TestParse(t *testing.T) {

Expand Down
24 changes: 24 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,27 @@ func ExampleParse_withFragment() {
fmt.Printf("%#v", d)
// Output: &did.DID{Method:"example", ID:"q7ckgxeq1lxmra0r", IDStrings:[]string{"q7ckgxeq1lxmra0r"}, Path:"", PathSegments:[]string(nil), Fragment:"keys-1"}
}

func ExampleDID_String() {
d := &did.DID{Method: "example", ID: "q7ckgxeq1lxmra0r"}
fmt.Println(d)
// Output: did:example:q7ckgxeq1lxmra0r
}

func ExampleDID_String_withPath() {
d := &did.DID{Method: "example", ID: "q7ckgxeq1lxmra0r", Path: "a/b"}
fmt.Println(d)
// Output: did:example:q7ckgxeq1lxmra0r/a/b
}

func ExampleDID_String_withPathSegments() {
d := &did.DID{Method: "example", ID: "q7ckgxeq1lxmra0r", PathSegments: []string{"a", "b"}}
fmt.Println(d)
// Output: did:example:q7ckgxeq1lxmra0r/a/b
}

func ExampleDID_String_withFragment() {
d := &did.DID{Method: "example", ID: "q7ckgxeq1lxmra0r", Fragment: "keys-1"}
fmt.Println(d)
// Output: did:example:q7ckgxeq1lxmra0r#keys-1
}

0 comments on commit cdf8b26

Please sign in to comment.