Skip to content

Commit

Permalink
dynamic/msgregistry: Add typed errors for lookups
Browse files Browse the repository at this point in the history
Adds typed errors used when looking up a
message and finding an enum or vice versa.
  • Loading branch information
johanbrandhorst committed Mar 2, 2021
1 parent a735446 commit 6d88177
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
48 changes: 44 additions & 4 deletions dynamic/msgregistry/message_registry.go
Expand Up @@ -22,6 +22,42 @@ import (

const googleApisDomain = "type.googleapis.com"

// ErrUnexpectedEnum is returned if the URL that was requested
// resolved to an enum instead of a message.
type ErrUnexpectedEnum struct {
URL string
FullyQualifiedName string
}

func (e *ErrUnexpectedEnum) Error() string {
return fmt.Sprintf("type for URL %q is the wrong type: wanted message, got enum", e.URL)
}

// Is determines how ErrUnexpectedEnum is compared
// against other errors when using errors.Is.
func (e *ErrUnexpectedEnum) Is(err error) bool {
_, ok := err.(*ErrUnexpectedEnum)
return ok
}

// ErrUnexpectedMessage is returned if the URL that was requested
// resolved to a message instead of an enum.
type ErrUnexpectedMessage struct {
URL string
FullyQualifiedName string
}

func (e *ErrUnexpectedMessage) Error() string {
return fmt.Sprintf("type for URL %q is the wrong type: wanted enum, got message", e.URL)
}

// Is determines how ErrUnexpectedMessage is compared
// against other errors when using errors.Is.
func (e *ErrUnexpectedMessage) Is(err error) bool {
_, ok := err.(*ErrUnexpectedMessage)
return ok
}

// MessageRegistry is a registry that maps URLs to message types. It allows for marshalling
// and unmarshalling Any types to and from dynamic messages.
type MessageRegistry struct {
Expand Down Expand Up @@ -188,8 +224,10 @@ func (r *MessageRegistry) getRegisteredMessageTypeByUrl(url string) (*desc.Messa
if m != nil {
if md, ok := m.(*desc.MessageDescriptor); ok {
return md, nil
} else {
return nil, fmt.Errorf("type for URL %v is the wrong type: wanted message, got enum", url)
}
return nil, &ErrUnexpectedEnum{
URL: url,
FullyQualifiedName: m.GetFullyQualifiedName(),
}
}
}
Expand Down Expand Up @@ -236,8 +274,10 @@ func (r *MessageRegistry) getRegisteredEnumTypeByUrl(url string) (*desc.EnumDesc
if m != nil {
if ed, ok := m.(*desc.EnumDescriptor); ok {
return ed, nil
} else {
return nil, fmt.Errorf("type for URL %v is the wrong type: wanted enum, got message", url)
}
return nil, &ErrUnexpectedMessage{
URL: url,
FullyQualifiedName: m.GetFullyQualifiedName(),
}
}
return nil, nil
Expand Down
5 changes: 3 additions & 2 deletions dynamic/msgregistry/message_registry_test.go
@@ -1,6 +1,7 @@
package msgregistry

import (
"errors"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -59,9 +60,9 @@ func TestMessageRegistry_LookupTypes(t *testing.T) {

// wrong type
_, err = mr.FindMessageTypeByUrl("foo.bar/google.protobuf.FieldDescriptorProto.Type")
testutil.Require(t, err != nil && strings.Contains(err.Error(), "wanted message, got enum"))
testutil.Require(t, errors.Is(err, &ErrUnexpectedEnum{}))
_, err = mr.FindEnumTypeByUrl("foo.bar/google.protobuf.DescriptorProto")
testutil.Require(t, err != nil && strings.Contains(err.Error(), "wanted enum, got message"))
testutil.Require(t, errors.Is(err, &ErrUnexpectedMessage{}))

// unmarshal any successfully finds the registered type
b, err := proto.Marshal(md.AsProto())
Expand Down

0 comments on commit 6d88177

Please sign in to comment.