1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsenpackage impl 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenimport ( 8*1c12ee1eSDan Willemsen "fmt" 9*1c12ee1eSDan Willemsen "reflect" 10*1c12ee1eSDan Willemsen "strconv" 11*1c12ee1eSDan Willemsen 12*1c12ee1eSDan Willemsen "google.golang.org/protobuf/encoding/prototext" 13*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/errors" 14*1c12ee1eSDan Willemsen "google.golang.org/protobuf/proto" 15*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoreflect" 16*1c12ee1eSDan Willemsen "google.golang.org/protobuf/runtime/protoiface" 17*1c12ee1eSDan Willemsen) 18*1c12ee1eSDan Willemsen 19*1c12ee1eSDan Willemsen// Export is a zero-length named type that exists only to export a set of 20*1c12ee1eSDan Willemsen// functions that we do not want to appear in godoc. 21*1c12ee1eSDan Willemsentype Export struct{} 22*1c12ee1eSDan Willemsen 23*1c12ee1eSDan Willemsen// NewError formats a string according to the format specifier and arguments and 24*1c12ee1eSDan Willemsen// returns an error that has a "proto" prefix. 25*1c12ee1eSDan Willemsenfunc (Export) NewError(f string, x ...interface{}) error { 26*1c12ee1eSDan Willemsen return errors.New(f, x...) 27*1c12ee1eSDan Willemsen} 28*1c12ee1eSDan Willemsen 29*1c12ee1eSDan Willemsen// enum is any enum type generated by protoc-gen-go 30*1c12ee1eSDan Willemsen// and must be a named int32 type. 31*1c12ee1eSDan Willemsentype enum = interface{} 32*1c12ee1eSDan Willemsen 33*1c12ee1eSDan Willemsen// EnumOf returns the protoreflect.Enum interface over e. 34*1c12ee1eSDan Willemsen// It returns nil if e is nil. 35*1c12ee1eSDan Willemsenfunc (Export) EnumOf(e enum) protoreflect.Enum { 36*1c12ee1eSDan Willemsen switch e := e.(type) { 37*1c12ee1eSDan Willemsen case nil: 38*1c12ee1eSDan Willemsen return nil 39*1c12ee1eSDan Willemsen case protoreflect.Enum: 40*1c12ee1eSDan Willemsen return e 41*1c12ee1eSDan Willemsen default: 42*1c12ee1eSDan Willemsen return legacyWrapEnum(reflect.ValueOf(e)) 43*1c12ee1eSDan Willemsen } 44*1c12ee1eSDan Willemsen} 45*1c12ee1eSDan Willemsen 46*1c12ee1eSDan Willemsen// EnumDescriptorOf returns the protoreflect.EnumDescriptor for e. 47*1c12ee1eSDan Willemsen// It returns nil if e is nil. 48*1c12ee1eSDan Willemsenfunc (Export) EnumDescriptorOf(e enum) protoreflect.EnumDescriptor { 49*1c12ee1eSDan Willemsen switch e := e.(type) { 50*1c12ee1eSDan Willemsen case nil: 51*1c12ee1eSDan Willemsen return nil 52*1c12ee1eSDan Willemsen case protoreflect.Enum: 53*1c12ee1eSDan Willemsen return e.Descriptor() 54*1c12ee1eSDan Willemsen default: 55*1c12ee1eSDan Willemsen return LegacyLoadEnumDesc(reflect.TypeOf(e)) 56*1c12ee1eSDan Willemsen } 57*1c12ee1eSDan Willemsen} 58*1c12ee1eSDan Willemsen 59*1c12ee1eSDan Willemsen// EnumTypeOf returns the protoreflect.EnumType for e. 60*1c12ee1eSDan Willemsen// It returns nil if e is nil. 61*1c12ee1eSDan Willemsenfunc (Export) EnumTypeOf(e enum) protoreflect.EnumType { 62*1c12ee1eSDan Willemsen switch e := e.(type) { 63*1c12ee1eSDan Willemsen case nil: 64*1c12ee1eSDan Willemsen return nil 65*1c12ee1eSDan Willemsen case protoreflect.Enum: 66*1c12ee1eSDan Willemsen return e.Type() 67*1c12ee1eSDan Willemsen default: 68*1c12ee1eSDan Willemsen return legacyLoadEnumType(reflect.TypeOf(e)) 69*1c12ee1eSDan Willemsen } 70*1c12ee1eSDan Willemsen} 71*1c12ee1eSDan Willemsen 72*1c12ee1eSDan Willemsen// EnumStringOf returns the enum value as a string, either as the name if 73*1c12ee1eSDan Willemsen// the number is resolvable, or the number formatted as a string. 74*1c12ee1eSDan Willemsenfunc (Export) EnumStringOf(ed protoreflect.EnumDescriptor, n protoreflect.EnumNumber) string { 75*1c12ee1eSDan Willemsen ev := ed.Values().ByNumber(n) 76*1c12ee1eSDan Willemsen if ev != nil { 77*1c12ee1eSDan Willemsen return string(ev.Name()) 78*1c12ee1eSDan Willemsen } 79*1c12ee1eSDan Willemsen return strconv.Itoa(int(n)) 80*1c12ee1eSDan Willemsen} 81*1c12ee1eSDan Willemsen 82*1c12ee1eSDan Willemsen// message is any message type generated by protoc-gen-go 83*1c12ee1eSDan Willemsen// and must be a pointer to a named struct type. 84*1c12ee1eSDan Willemsentype message = interface{} 85*1c12ee1eSDan Willemsen 86*1c12ee1eSDan Willemsen// legacyMessageWrapper wraps a v2 message as a v1 message. 87*1c12ee1eSDan Willemsentype legacyMessageWrapper struct{ m protoreflect.ProtoMessage } 88*1c12ee1eSDan Willemsen 89*1c12ee1eSDan Willemsenfunc (m legacyMessageWrapper) Reset() { proto.Reset(m.m) } 90*1c12ee1eSDan Willemsenfunc (m legacyMessageWrapper) String() string { return Export{}.MessageStringOf(m.m) } 91*1c12ee1eSDan Willemsenfunc (m legacyMessageWrapper) ProtoMessage() {} 92*1c12ee1eSDan Willemsen 93*1c12ee1eSDan Willemsen// ProtoMessageV1Of converts either a v1 or v2 message to a v1 message. 94*1c12ee1eSDan Willemsen// It returns nil if m is nil. 95*1c12ee1eSDan Willemsenfunc (Export) ProtoMessageV1Of(m message) protoiface.MessageV1 { 96*1c12ee1eSDan Willemsen switch mv := m.(type) { 97*1c12ee1eSDan Willemsen case nil: 98*1c12ee1eSDan Willemsen return nil 99*1c12ee1eSDan Willemsen case protoiface.MessageV1: 100*1c12ee1eSDan Willemsen return mv 101*1c12ee1eSDan Willemsen case unwrapper: 102*1c12ee1eSDan Willemsen return Export{}.ProtoMessageV1Of(mv.protoUnwrap()) 103*1c12ee1eSDan Willemsen case protoreflect.ProtoMessage: 104*1c12ee1eSDan Willemsen return legacyMessageWrapper{mv} 105*1c12ee1eSDan Willemsen default: 106*1c12ee1eSDan Willemsen panic(fmt.Sprintf("message %T is neither a v1 or v2 Message", m)) 107*1c12ee1eSDan Willemsen } 108*1c12ee1eSDan Willemsen} 109*1c12ee1eSDan Willemsen 110*1c12ee1eSDan Willemsenfunc (Export) protoMessageV2Of(m message) protoreflect.ProtoMessage { 111*1c12ee1eSDan Willemsen switch mv := m.(type) { 112*1c12ee1eSDan Willemsen case nil: 113*1c12ee1eSDan Willemsen return nil 114*1c12ee1eSDan Willemsen case protoreflect.ProtoMessage: 115*1c12ee1eSDan Willemsen return mv 116*1c12ee1eSDan Willemsen case legacyMessageWrapper: 117*1c12ee1eSDan Willemsen return mv.m 118*1c12ee1eSDan Willemsen case protoiface.MessageV1: 119*1c12ee1eSDan Willemsen return nil 120*1c12ee1eSDan Willemsen default: 121*1c12ee1eSDan Willemsen panic(fmt.Sprintf("message %T is neither a v1 or v2 Message", m)) 122*1c12ee1eSDan Willemsen } 123*1c12ee1eSDan Willemsen} 124*1c12ee1eSDan Willemsen 125*1c12ee1eSDan Willemsen// ProtoMessageV2Of converts either a v1 or v2 message to a v2 message. 126*1c12ee1eSDan Willemsen// It returns nil if m is nil. 127*1c12ee1eSDan Willemsenfunc (Export) ProtoMessageV2Of(m message) protoreflect.ProtoMessage { 128*1c12ee1eSDan Willemsen if m == nil { 129*1c12ee1eSDan Willemsen return nil 130*1c12ee1eSDan Willemsen } 131*1c12ee1eSDan Willemsen if mv := (Export{}).protoMessageV2Of(m); mv != nil { 132*1c12ee1eSDan Willemsen return mv 133*1c12ee1eSDan Willemsen } 134*1c12ee1eSDan Willemsen return legacyWrapMessage(reflect.ValueOf(m)).Interface() 135*1c12ee1eSDan Willemsen} 136*1c12ee1eSDan Willemsen 137*1c12ee1eSDan Willemsen// MessageOf returns the protoreflect.Message interface over m. 138*1c12ee1eSDan Willemsen// It returns nil if m is nil. 139*1c12ee1eSDan Willemsenfunc (Export) MessageOf(m message) protoreflect.Message { 140*1c12ee1eSDan Willemsen if m == nil { 141*1c12ee1eSDan Willemsen return nil 142*1c12ee1eSDan Willemsen } 143*1c12ee1eSDan Willemsen if mv := (Export{}).protoMessageV2Of(m); mv != nil { 144*1c12ee1eSDan Willemsen return mv.ProtoReflect() 145*1c12ee1eSDan Willemsen } 146*1c12ee1eSDan Willemsen return legacyWrapMessage(reflect.ValueOf(m)) 147*1c12ee1eSDan Willemsen} 148*1c12ee1eSDan Willemsen 149*1c12ee1eSDan Willemsen// MessageDescriptorOf returns the protoreflect.MessageDescriptor for m. 150*1c12ee1eSDan Willemsen// It returns nil if m is nil. 151*1c12ee1eSDan Willemsenfunc (Export) MessageDescriptorOf(m message) protoreflect.MessageDescriptor { 152*1c12ee1eSDan Willemsen if m == nil { 153*1c12ee1eSDan Willemsen return nil 154*1c12ee1eSDan Willemsen } 155*1c12ee1eSDan Willemsen if mv := (Export{}).protoMessageV2Of(m); mv != nil { 156*1c12ee1eSDan Willemsen return mv.ProtoReflect().Descriptor() 157*1c12ee1eSDan Willemsen } 158*1c12ee1eSDan Willemsen return LegacyLoadMessageDesc(reflect.TypeOf(m)) 159*1c12ee1eSDan Willemsen} 160*1c12ee1eSDan Willemsen 161*1c12ee1eSDan Willemsen// MessageTypeOf returns the protoreflect.MessageType for m. 162*1c12ee1eSDan Willemsen// It returns nil if m is nil. 163*1c12ee1eSDan Willemsenfunc (Export) MessageTypeOf(m message) protoreflect.MessageType { 164*1c12ee1eSDan Willemsen if m == nil { 165*1c12ee1eSDan Willemsen return nil 166*1c12ee1eSDan Willemsen } 167*1c12ee1eSDan Willemsen if mv := (Export{}).protoMessageV2Of(m); mv != nil { 168*1c12ee1eSDan Willemsen return mv.ProtoReflect().Type() 169*1c12ee1eSDan Willemsen } 170*1c12ee1eSDan Willemsen return legacyLoadMessageType(reflect.TypeOf(m), "") 171*1c12ee1eSDan Willemsen} 172*1c12ee1eSDan Willemsen 173*1c12ee1eSDan Willemsen// MessageStringOf returns the message value as a string, 174*1c12ee1eSDan Willemsen// which is the message serialized in the protobuf text format. 175*1c12ee1eSDan Willemsenfunc (Export) MessageStringOf(m protoreflect.ProtoMessage) string { 176*1c12ee1eSDan Willemsen return prototext.MarshalOptions{Multiline: false}.Format(m) 177*1c12ee1eSDan Willemsen} 178