package ptypes
import (
"fmt"
"strings"
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
anypb "github.com/golang/protobuf/ptypes/any"
)
const urlPrefix = "type.googleapis.com/"
func AnyMessageName (any *anypb .Any ) (string , error ) {
name , err := anyMessageName (any )
return string (name ), err
}
func anyMessageName(any *anypb .Any ) (protoreflect .FullName , error ) {
if any == nil {
return "" , fmt .Errorf ("message is nil" )
}
name := protoreflect .FullName (any .TypeUrl )
if i := strings .LastIndex (any .TypeUrl , "/" ); i >= 0 {
name = name [i +len ("/" ):]
}
if !name .IsValid () {
return "" , fmt .Errorf ("message type url %q is invalid" , any .TypeUrl )
}
return name , nil
}
func MarshalAny (m proto .Message ) (*anypb .Any , error ) {
switch dm := m .(type ) {
case DynamicAny :
m = dm .Message
case *DynamicAny :
if dm == nil {
return nil , proto .ErrNil
}
m = dm .Message
}
b , err := proto .Marshal (m )
if err != nil {
return nil , err
}
return &anypb .Any {TypeUrl : urlPrefix + proto .MessageName (m ), Value : b }, nil
}
func Empty (any *anypb .Any ) (proto .Message , error ) {
name , err := anyMessageName (any )
if err != nil {
return nil , err
}
mt , err := protoregistry .GlobalTypes .FindMessageByName (name )
if err != nil {
return nil , err
}
return proto .MessageV1 (mt .New ().Interface ()), nil
}
func UnmarshalAny (any *anypb .Any , m proto .Message ) error {
if dm , ok := m .(*DynamicAny ); ok {
if dm .Message == nil {
var err error
dm .Message , err = Empty (any )
if err != nil {
return err
}
}
m = dm .Message
}
anyName , err := AnyMessageName (any )
if err != nil {
return err
}
msgName := proto .MessageName (m )
if anyName != msgName {
return fmt .Errorf ("mismatched message type: got %q want %q" , anyName , msgName )
}
return proto .Unmarshal (any .Value , m )
}
func Is (any *anypb .Any , m proto .Message ) bool {
if any == nil || m == nil {
return false
}
name := proto .MessageName (m )
if !strings .HasSuffix (any .TypeUrl , name ) {
return false
}
return len (any .TypeUrl ) == len (name ) || any .TypeUrl [len (any .TypeUrl )-len (name )-1 ] == '/'
}
type DynamicAny struct { proto .Message }
func (m DynamicAny ) String () string {
if m .Message == nil {
return "<nil>"
}
return m .Message .String ()
}
func (m DynamicAny ) Reset () {
if m .Message == nil {
return
}
m .Message .Reset ()
}
func (m DynamicAny ) ProtoMessage () {
return
}
func (m DynamicAny ) ProtoReflect () protoreflect .Message {
if m .Message == nil {
return nil
}
return dynamicAny {proto .MessageReflect (m .Message )}
}
type dynamicAny struct { protoreflect .Message }
func (m dynamicAny ) Type () protoreflect .MessageType {
return dynamicAnyType {m .Message .Type ()}
}
func (m dynamicAny ) New () protoreflect .Message {
return dynamicAnyType {m .Message .Type ()}.New ()
}
func (m dynamicAny ) Interface () protoreflect .ProtoMessage {
return DynamicAny {proto .MessageV1 (m .Message .Interface ())}
}
type dynamicAnyType struct { protoreflect .MessageType }
func (t dynamicAnyType ) New () protoreflect .Message {
return dynamicAny {t .MessageType .New ()}
}
func (t dynamicAnyType ) Zero () protoreflect .Message {
return dynamicAny {t .MessageType .Zero ()}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .