From 9476017463771b04f93b817974f37149d22cf38a Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Mon, 20 Mar 2023 14:49:18 +0100 Subject: DocumentId -> Id --- client/go/internal/vespa/document/document.go | 189 +++++++++++---------- client/go/internal/vespa/document/document_test.go | 30 ++-- client/go/internal/vespa/document/feeder.go | 2 +- client/go/internal/vespa/document/http.go | 4 +- client/go/internal/vespa/document/http_test.go | 12 +- 5 files changed, 119 insertions(+), 118 deletions(-) (limited to 'client') diff --git a/client/go/internal/vespa/document/document.go b/client/go/internal/vespa/document/document.go index 0b23df18735..6f34d3efe1a 100644 --- a/client/go/internal/vespa/document/document.go +++ b/client/go/internal/vespa/document/document.go @@ -19,8 +19,94 @@ const ( OperationRemove ) +// Id represents a Vespa document ID. +type Id struct { + Type string + Namespace string + Number *int64 + Group string + UserSpecific string +} + +func (d Id) Equal(o Id) bool { + return d.Type == o.Type && + d.Namespace == o.Namespace && + ((d.Number == nil && o.Number == nil) || *d.Number == *o.Number) && + d.Group == o.Group && + d.UserSpecific == o.UserSpecific +} + +func (d Id) String() string { + var sb strings.Builder + sb.WriteString("id:") + sb.WriteString(d.Namespace) + sb.WriteString(":") + sb.WriteString(d.Type) + sb.WriteString(":") + if d.Number != nil { + sb.WriteString("n=") + sb.WriteString(strconv.FormatInt(*d.Number, 10)) + } else if d.Group != "" { + sb.WriteString("g=") + sb.WriteString(d.Group) + } + sb.WriteString(":") + sb.WriteString(d.UserSpecific) + return sb.String() +} + +// ParseId parses a serialized document ID string. +func ParseId(serialized string) (Id, error) { + parts := strings.SplitN(serialized, ":", 4) + if len(parts) < 4 || parts[0] != "id" { + return Id{}, parseError(serialized) + } + namespace := parts[1] + if namespace == "" { + return Id{}, parseError(serialized) + } + docType := parts[2] + if docType == "" { + return Id{}, parseError(serialized) + } + rest := strings.SplitN(parts[3], ":", 2) + if len(rest) < 2 { + return Id{}, parseError(serialized) + } + var number *int64 + group := "" + userSpecific := "" + for _, part := range rest { + if number == nil && strings.HasPrefix(part, "n=") { + n, err := strconv.ParseInt(part[2:], 10, 64) + if err != nil { + return Id{}, parseError(serialized) + } + number = &n + } else if group == "" && strings.HasPrefix(part, "g=") { + group = part[2:] + if len(group) == 0 { + return Id{}, parseError(serialized) + } + } else { + userSpecific = part + } + } + if userSpecific == "" { + return Id{}, parseError(serialized) + } + return Id{ + Namespace: namespace, + Type: docType, + Number: number, + Group: group, + UserSpecific: userSpecific, + }, nil +} + +// Document represents a Vespa document, and its operation. type Document struct { - Id DocumentId + Id Id Operation Operation IdString string `json:"id"` @@ -118,6 +204,14 @@ func (d *Decoder) decode() (Document, error) { return doc, nil } +func NewDecoder(r io.Reader) *Decoder { + buf := bufio.NewReader(r) + return &Decoder{ + buf: buf, + dec: json.NewDecoder(buf), + } +} + func parseDocument(d *Document) error { id := "" if d.IdString != "" { @@ -143,99 +237,6 @@ func parseDocument(d *Document) error { return nil } -func NewDecoder(r io.Reader) *Decoder { - buf := bufio.NewReader(r) - return &Decoder{ - buf: buf, - dec: json.NewDecoder(buf), - } -} - -// A Vespa document ID. -type DocumentId struct { - Type string - Namespace string - Number *int64 - Group string - UserSpecific string -} - -func (d DocumentId) Equal(o DocumentId) bool { - return d.Type == o.Type && - d.Namespace == o.Namespace && - ((d.Number == nil && o.Number == nil) || *d.Number == *o.Number) && - d.Group == o.Group && - d.UserSpecific == o.UserSpecific -} - -func (d DocumentId) String() string { - var sb strings.Builder - sb.WriteString("id:") - sb.WriteString(d.Namespace) - sb.WriteString(":") - sb.WriteString(d.Type) - sb.WriteString(":") - if d.Number != nil { - sb.WriteString("n=") - sb.WriteString(strconv.FormatInt(*d.Number, 10)) - } else if d.Group != "" { - sb.WriteString("g=") - sb.WriteString(d.Group) - } - sb.WriteString(":") - sb.WriteString(d.UserSpecific) - return sb.String() -} - func parseError(value string) error { return fmt.Errorf("invalid document: expected id:::[n=|g=]:, got %q", value) } - -// ParseId parses a serialized document ID string. -func ParseId(serialized string) (DocumentId, error) { - parts := strings.SplitN(serialized, ":", 4) - if len(parts) < 4 || parts[0] != "id" { - return DocumentId{}, parseError(serialized) - } - namespace := parts[1] - if namespace == "" { - return DocumentId{}, parseError(serialized) - } - docType := parts[2] - if docType == "" { - return DocumentId{}, parseError(serialized) - } - rest := strings.SplitN(parts[3], ":", 2) - if len(rest) < 2 { - return DocumentId{}, parseError(serialized) - } - var number *int64 - group := "" - userSpecific := "" - for _, part := range rest { - if number == nil && strings.HasPrefix(part, "n=") { - n, err := strconv.ParseInt(part[2:], 10, 64) - if err != nil { - return DocumentId{}, parseError(serialized) - } - number = &n - } else if group == "" && strings.HasPrefix(part, "g=") { - group = part[2:] - if len(group) == 0 { - return DocumentId{}, parseError(serialized) - } - } else { - userSpecific = part - } - } - if userSpecific == "" { - return DocumentId{}, parseError(serialized) - } - return DocumentId{ - Namespace: namespace, - Type: docType, - Number: number, - Group: group, - UserSpecific: userSpecific, - }, nil -} diff --git a/client/go/internal/vespa/document/document_test.go b/client/go/internal/vespa/document/document_test.go index 4bd79cf0796..21e97fd4e46 100644 --- a/client/go/internal/vespa/document/document_test.go +++ b/client/go/internal/vespa/document/document_test.go @@ -21,11 +21,11 @@ func mustParseDocument(d Document) Document { func TestParseId(t *testing.T) { tests := []struct { in string - out DocumentId + out Id fail bool }{ {"id:ns:type::user", - DocumentId{ + Id{ Namespace: "ns", Type: "type", UserSpecific: "user", @@ -33,7 +33,7 @@ func TestParseId(t *testing.T) { false, }, {"id:ns:type:n=123:user", - DocumentId{ + Id{ Namespace: "ns", Type: "type", Number: ptr(int64(123)), @@ -42,7 +42,7 @@ func TestParseId(t *testing.T) { false, }, {"id:ns:type:g=foo:user", - DocumentId{ + Id{ Namespace: "ns", Type: "type", Group: "foo", @@ -51,7 +51,7 @@ func TestParseId(t *testing.T) { false, }, {"id:ns:type::user::specific", - DocumentId{ + Id{ Namespace: "ns", Type: "type", UserSpecific: "user::specific", @@ -59,22 +59,22 @@ func TestParseId(t *testing.T) { false, }, {"id:ns:type:::", - DocumentId{ + Id{ Namespace: "ns", Type: "type", UserSpecific: ":", }, false, }, - {"", DocumentId{}, true}, - {"foobar", DocumentId{}, true}, - {"idd:ns:type:user", DocumentId{}, true}, - {"id:ns::user", DocumentId{}, true}, - {"id::type:user", DocumentId{}, true}, - {"id:ns:type:g=:user", DocumentId{}, true}, - {"id:ns:type:n=:user", DocumentId{}, true}, - {"id:ns:type:n=foo:user", DocumentId{}, true}, - {"id:ns:type::", DocumentId{}, true}, + {"", Id{}, true}, + {"foobar", Id{}, true}, + {"idd:ns:type:user", Id{}, true}, + {"id:ns::user", Id{}, true}, + {"id::type:user", Id{}, true}, + {"id:ns:type:g=:user", Id{}, true}, + {"id:ns:type:n=:user", Id{}, true}, + {"id:ns:type:n=foo:user", Id{}, true}, + {"id:ns:type::", Id{}, true}, } for i, tt := range tests { parsed, err := ParseId(tt.in) diff --git a/client/go/internal/vespa/document/feeder.go b/client/go/internal/vespa/document/feeder.go index 6a0249ab9b9..732db051dab 100644 --- a/client/go/internal/vespa/document/feeder.go +++ b/client/go/internal/vespa/document/feeder.go @@ -23,7 +23,7 @@ const ( // Result represents the result of a feeding operation. type Result struct { - Id DocumentId + Id Id Status Status Message string Trace string diff --git a/client/go/internal/vespa/document/http.go b/client/go/internal/vespa/document/http.go index eed92c8cbcf..2f0d085085c 100644 --- a/client/go/internal/vespa/document/http.go +++ b/client/go/internal/vespa/document/http.go @@ -66,7 +66,7 @@ func (c *Client) queryParams() url.Values { return params } -func urlPath(id DocumentId) string { +func urlPath(id Id) string { var sb strings.Builder sb.WriteString("/document/v1/") sb.WriteString(url.PathEscape(id.Namespace)) @@ -157,7 +157,7 @@ func (c *Client) addStats(stats *Stats) { c.stats.Add(*stats) } -func (c *Client) createResult(id DocumentId, stats *Stats, resp *http.Response) Result { +func (c *Client) createResult(id Id, stats *Stats, resp *http.Response) Result { result := Result{Id: id} switch resp.StatusCode { case 200: diff --git a/client/go/internal/vespa/document/http_test.go b/client/go/internal/vespa/document/http_test.go index fe0ad28e86e..ca59c4c2af0 100644 --- a/client/go/internal/vespa/document/http_test.go +++ b/client/go/internal/vespa/document/http_test.go @@ -88,11 +88,11 @@ func TestClientSend(t *testing.T) { func TestURLPath(t *testing.T) { tests := []struct { - in DocumentId + in Id out string }{ { - DocumentId{ + Id{ Namespace: "ns-with-/", Type: "type-with-/", UserSpecific: "user", @@ -100,7 +100,7 @@ func TestURLPath(t *testing.T) { "/document/v1/ns-with-%2F/type-with-%2F/docid/user", }, { - DocumentId{ + Id{ Namespace: "ns", Type: "type", Number: ptr(int64(123)), @@ -109,7 +109,7 @@ func TestURLPath(t *testing.T) { "/document/v1/ns/type/number/123/user", }, { - DocumentId{ + Id{ Namespace: "ns", Type: "type", Group: "foo", @@ -118,7 +118,7 @@ func TestURLPath(t *testing.T) { "/document/v1/ns/type/group/foo/user", }, { - DocumentId{ + Id{ Namespace: "ns", Type: "type", UserSpecific: "user::specific", @@ -126,7 +126,7 @@ func TestURLPath(t *testing.T) { "/document/v1/ns/type/docid/user::specific", }, { - DocumentId{ + Id{ Namespace: "ns", Type: "type", UserSpecific: ":", -- cgit v1.2.3