...

Source file src/github.com/golang/protobuf/ptypes/any.go

Documentation: github.com/golang/protobuf/ptypes

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ptypes
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  
    11  	"github.com/golang/protobuf/proto"
    12  	"google.golang.org/protobuf/reflect/protoreflect"
    13  	"google.golang.org/protobuf/reflect/protoregistry"
    14  
    15  	anypb "github.com/golang/protobuf/ptypes/any"
    16  )
    17  
    18  const urlPrefix = "type.googleapis.com/"
    19  
    20  // AnyMessageName returns the message name contained in an anypb.Any message.
    21  // Most type assertions should use the Is function instead.
    22  //
    23  // Deprecated: Call the any.MessageName method instead.
    24  func AnyMessageName(any *anypb.Any) (string, error) {
    25  	name, err := anyMessageName(any)
    26  	return string(name), err
    27  }
    28  func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) {
    29  	if any == nil {
    30  		return "", fmt.Errorf("message is nil")
    31  	}
    32  	name := protoreflect.FullName(any.TypeUrl)
    33  	if i := strings.LastIndex(any.TypeUrl, "/"); i >= 0 {
    34  		name = name[i+len("/"):]
    35  	}
    36  	if !name.IsValid() {
    37  		return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
    38  	}
    39  	return name, nil
    40  }
    41  
    42  // MarshalAny marshals the given message m into an anypb.Any message.
    43  //
    44  // Deprecated: Call the anypb.New function instead.
    45  func MarshalAny(m proto.Message) (*anypb.Any, error) {
    46  	switch dm := m.(type) {
    47  	case DynamicAny:
    48  		m = dm.Message
    49  	case *DynamicAny:
    50  		if dm == nil {
    51  			return nil, proto.ErrNil
    52  		}
    53  		m = dm.Message
    54  	}
    55  	b, err := proto.Marshal(m)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	return &anypb.Any{TypeUrl: urlPrefix + proto.MessageName(m), Value: b}, nil
    60  }
    61  
    62  // Empty returns a new message of the type specified in an anypb.Any message.
    63  // It returns protoregistry.NotFound if the corresponding message type could not
    64  // be resolved in the global registry.
    65  //
    66  // Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead
    67  // to resolve the message name and create a new instance of it.
    68  func Empty(any *anypb.Any) (proto.Message, error) {
    69  	name, err := anyMessageName(any)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	mt, err := protoregistry.GlobalTypes.FindMessageByName(name)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return proto.MessageV1(mt.New().Interface()), nil
    78  }
    79  
    80  // UnmarshalAny unmarshals the encoded value contained in the anypb.Any message
    81  // into the provided message m. It returns an error if the target message
    82  // does not match the type in the Any message or if an unmarshal error occurs.
    83  //
    84  // The target message m may be a *DynamicAny message. If the underlying message
    85  // type could not be resolved, then this returns protoregistry.NotFound.
    86  //
    87  // Deprecated: Call the any.UnmarshalTo method instead.
    88  func UnmarshalAny(any *anypb.Any, m proto.Message) error {
    89  	if dm, ok := m.(*DynamicAny); ok {
    90  		if dm.Message == nil {
    91  			var err error
    92  			dm.Message, err = Empty(any)
    93  			if err != nil {
    94  				return err
    95  			}
    96  		}
    97  		m = dm.Message
    98  	}
    99  
   100  	anyName, err := AnyMessageName(any)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	msgName := proto.MessageName(m)
   105  	if anyName != msgName {
   106  		return fmt.Errorf("mismatched message type: got %q want %q", anyName, msgName)
   107  	}
   108  	return proto.Unmarshal(any.Value, m)
   109  }
   110  
   111  // Is reports whether the Any message contains a message of the specified type.
   112  //
   113  // Deprecated: Call the any.MessageIs method instead.
   114  func Is(any *anypb.Any, m proto.Message) bool {
   115  	if any == nil || m == nil {
   116  		return false
   117  	}
   118  	name := proto.MessageName(m)
   119  	if !strings.HasSuffix(any.TypeUrl, name) {
   120  		return false
   121  	}
   122  	return len(any.TypeUrl) == len(name) || any.TypeUrl[len(any.TypeUrl)-len(name)-1] == '/'
   123  }
   124  
   125  // DynamicAny is a value that can be passed to UnmarshalAny to automatically
   126  // allocate a proto.Message for the type specified in an anypb.Any message.
   127  // The allocated message is stored in the embedded proto.Message.
   128  //
   129  // Example:
   130  //
   131  //	var x ptypes.DynamicAny
   132  //	if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
   133  //	fmt.Printf("unmarshaled message: %v", x.Message)
   134  //
   135  // Deprecated: Use the any.UnmarshalNew method instead to unmarshal
   136  // the any message contents into a new instance of the underlying message.
   137  type DynamicAny struct{ proto.Message }
   138  
   139  func (m DynamicAny) String() string {
   140  	if m.Message == nil {
   141  		return "<nil>"
   142  	}
   143  	return m.Message.String()
   144  }
   145  func (m DynamicAny) Reset() {
   146  	if m.Message == nil {
   147  		return
   148  	}
   149  	m.Message.Reset()
   150  }
   151  func (m DynamicAny) ProtoMessage() {
   152  	return
   153  }
   154  func (m DynamicAny) ProtoReflect() protoreflect.Message {
   155  	if m.Message == nil {
   156  		return nil
   157  	}
   158  	return dynamicAny{proto.MessageReflect(m.Message)}
   159  }
   160  
   161  type dynamicAny struct{ protoreflect.Message }
   162  
   163  func (m dynamicAny) Type() protoreflect.MessageType {
   164  	return dynamicAnyType{m.Message.Type()}
   165  }
   166  func (m dynamicAny) New() protoreflect.Message {
   167  	return dynamicAnyType{m.Message.Type()}.New()
   168  }
   169  func (m dynamicAny) Interface() protoreflect.ProtoMessage {
   170  	return DynamicAny{proto.MessageV1(m.Message.Interface())}
   171  }
   172  
   173  type dynamicAnyType struct{ protoreflect.MessageType }
   174  
   175  func (t dynamicAnyType) New() protoreflect.Message {
   176  	return dynamicAny{t.MessageType.New()}
   177  }
   178  func (t dynamicAnyType) Zero() protoreflect.Message {
   179  	return dynamicAny{t.MessageType.Zero()}
   180  }
   181  

View as plain text