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