From d927bc2ecfe08521609c9efa2bd5a9b169ea58c4 Mon Sep 17 00:00:00 2001 From: Tom Daffurn Date: Fri, 2 Aug 2024 08:48:31 +1000 Subject: [PATCH] DID implements Scanner and Valuer interfaces (#161) * Implement Scanner and Valuer interfaces * lint --- dids/did/did.go | 22 +++++++++++++++++ dids/did/did_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/dids/did/did.go b/dids/did/did.go index 1ad7546..e1d8a05 100644 --- a/dids/did/did.go +++ b/dids/did/did.go @@ -1,7 +1,9 @@ package did import ( + "database/sql/driver" "errors" + "fmt" "regexp" "strings" ) @@ -65,6 +67,26 @@ func (d *DID) UnmarshalText(text []byte) error { return nil } +// Scan implements the Scanner interface +func (d *DID) Scan(src any) error { + switch obj := src.(type) { + case nil: + return nil + case string: + if src == "" { + return nil + } + return d.UnmarshalText([]byte(obj)) + default: + return fmt.Errorf("unsupported scan type %T", obj) + } +} + +// Value implements the driver Valuer interface +func (d DID) Value() (driver.Value, error) { + return d.String(), nil +} + // relevant ABNF rules: https://www.w3.org/TR/did-core/#did-syntax var ( pctEncodedPattern = `(?:%[0-9a-fA-F]{2})` diff --git a/dids/did/did_test.go b/dids/did/did_test.go index 0cdbf05..0adfef1 100644 --- a/dids/did/did_test.go +++ b/dids/did/did_test.go @@ -115,3 +115,59 @@ func TestParse(t *testing.T) { } } } + +func TestDID_ScanValueRoundtrip(t *testing.T) { + tests := []struct { + object did.DID + raw string + wantErr bool + }{ + { + raw: "did:example:123456789abcdefghi", + object: MustParse("did:example:123456789abcdefghi"), + }, + { + raw: "did:example:123456789abcdefghi;foo=bar;baz=qux", + object: MustParse("did:example:123456789abcdefghi;foo=bar;baz=qux"), + }, + { + raw: "did:example:123456789abcdefghi?foo=bar&baz=qux", + object: MustParse("did:example:123456789abcdefghi?foo=bar&baz=qux"), + }, + { + raw: "did:example:123456789abcdefghi#keys-1", + object: MustParse("did:example:123456789abcdefghi#keys-1"), + }, + { + raw: "did:example:123456789abcdefghi?foo=bar&baz=qux#keys-1", + object: MustParse("did:example:123456789abcdefghi?foo=bar&baz=qux#keys-1"), + }, + { + raw: "did:example:123456789abcdefghi;foo=bar;baz=qux?foo=bar&baz=qux#keys-1", + object: MustParse("did:example:123456789abcdefghi;foo=bar;baz=qux?foo=bar&baz=qux#keys-1"), + }, + } + for _, tt := range tests { + t.Run(tt.raw, func(t *testing.T) { + var d did.DID + if err := d.Scan(tt.raw); (err != nil) != tt.wantErr { + t.Errorf("Scan() error = %v, wantErr %v", err, tt.wantErr) + } + assert.Equal(t, tt.object, d) + + value, err := d.Value() + assert.NoError(t, err) + actual, ok := value.(string) + assert.True(t, ok) + assert.Equal(t, tt.raw, actual) + }) + } +} + +func MustParse(input string) did.DID { + d, err := did.Parse(input) + if err != nil { + panic(err) + } + return d +}