1// Copyright 2019 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 dynamicpb creates protocol buffer messages using runtime type information. 6package dynamicpb 7 8import ( 9 "math" 10 11 "google.golang.org/protobuf/internal/errors" 12 pref "google.golang.org/protobuf/reflect/protoreflect" 13 "google.golang.org/protobuf/runtime/protoiface" 14 "google.golang.org/protobuf/runtime/protoimpl" 15) 16 17// enum is a dynamic protoreflect.Enum. 18type enum struct { 19 num pref.EnumNumber 20 typ pref.EnumType 21} 22 23func (e enum) Descriptor() pref.EnumDescriptor { return e.typ.Descriptor() } 24func (e enum) Type() pref.EnumType { return e.typ } 25func (e enum) Number() pref.EnumNumber { return e.num } 26 27// enumType is a dynamic protoreflect.EnumType. 28type enumType struct { 29 desc pref.EnumDescriptor 30} 31 32// NewEnumType creates a new EnumType with the provided descriptor. 33// 34// EnumTypes created by this package are equal if their descriptors are equal. 35// That is, if ed1 == ed2, then NewEnumType(ed1) == NewEnumType(ed2). 36// 37// Enum values created by the EnumType are equal if their numbers are equal. 38func NewEnumType(desc pref.EnumDescriptor) pref.EnumType { 39 return enumType{desc} 40} 41 42func (et enumType) New(n pref.EnumNumber) pref.Enum { return enum{n, et} } 43func (et enumType) Descriptor() pref.EnumDescriptor { return et.desc } 44 45// extensionType is a dynamic protoreflect.ExtensionType. 46type extensionType struct { 47 desc extensionTypeDescriptor 48} 49 50// A Message is a dynamically constructed protocol buffer message. 51// 52// Message implements the proto.Message interface, and may be used with all 53// standard proto package functions such as Marshal, Unmarshal, and so forth. 54// 55// Message also implements the protoreflect.Message interface. See the protoreflect 56// package documentation for that interface for how to get and set fields and 57// otherwise interact with the contents of a Message. 58// 59// Reflection API functions which construct messages, such as NewField, 60// return new dynamic messages of the appropriate type. Functions which take 61// messages, such as Set for a message-value field, will accept any message 62// with a compatible type. 63// 64// Operations which modify a Message are not safe for concurrent use. 65type Message struct { 66 typ messageType 67 known map[pref.FieldNumber]pref.Value 68 ext map[pref.FieldNumber]pref.FieldDescriptor 69 unknown pref.RawFields 70} 71 72var ( 73 _ pref.Message = (*Message)(nil) 74 _ pref.ProtoMessage = (*Message)(nil) 75 _ protoiface.MessageV1 = (*Message)(nil) 76) 77 78// NewMessage creates a new message with the provided descriptor. 79func NewMessage(desc pref.MessageDescriptor) *Message { 80 return &Message{ 81 typ: messageType{desc}, 82 known: make(map[pref.FieldNumber]pref.Value), 83 ext: make(map[pref.FieldNumber]pref.FieldDescriptor), 84 } 85} 86 87// ProtoMessage implements the legacy message interface. 88func (m *Message) ProtoMessage() {} 89 90// ProtoReflect implements the protoreflect.ProtoMessage interface. 91func (m *Message) ProtoReflect() pref.Message { 92 return m 93} 94 95// String returns a string representation of a message. 96func (m *Message) String() string { 97 return protoimpl.X.MessageStringOf(m) 98} 99 100// Reset clears the message to be empty, but preserves the dynamic message type. 101func (m *Message) Reset() { 102 m.known = make(map[pref.FieldNumber]pref.Value) 103 m.ext = make(map[pref.FieldNumber]pref.FieldDescriptor) 104 m.unknown = nil 105} 106 107// Descriptor returns the message descriptor. 108func (m *Message) Descriptor() pref.MessageDescriptor { 109 return m.typ.desc 110} 111 112// Type returns the message type. 113func (m *Message) Type() pref.MessageType { 114 return m.typ 115} 116 117// New returns a newly allocated empty message with the same descriptor. 118// See protoreflect.Message for details. 119func (m *Message) New() pref.Message { 120 return m.Type().New() 121} 122 123// Interface returns the message. 124// See protoreflect.Message for details. 125func (m *Message) Interface() pref.ProtoMessage { 126 return m 127} 128 129// ProtoMethods is an internal detail of the protoreflect.Message interface. 130// Users should never call this directly. 131func (m *Message) ProtoMethods() *protoiface.Methods { 132 return nil 133} 134 135// Range visits every populated field in undefined order. 136// See protoreflect.Message for details. 137func (m *Message) Range(f func(pref.FieldDescriptor, pref.Value) bool) { 138 for num, v := range m.known { 139 fd := m.ext[num] 140 if fd == nil { 141 fd = m.Descriptor().Fields().ByNumber(num) 142 } 143 if !isSet(fd, v) { 144 continue 145 } 146 if !f(fd, v) { 147 return 148 } 149 } 150} 151 152// Has reports whether a field is populated. 153// See protoreflect.Message for details. 154func (m *Message) Has(fd pref.FieldDescriptor) bool { 155 m.checkField(fd) 156 if fd.IsExtension() && m.ext[fd.Number()] != fd { 157 return false 158 } 159 v, ok := m.known[fd.Number()] 160 if !ok { 161 return false 162 } 163 return isSet(fd, v) 164} 165 166// Clear clears a field. 167// See protoreflect.Message for details. 168func (m *Message) Clear(fd pref.FieldDescriptor) { 169 m.checkField(fd) 170 num := fd.Number() 171 delete(m.known, num) 172 delete(m.ext, num) 173} 174 175// Get returns the value of a field. 176// See protoreflect.Message for details. 177func (m *Message) Get(fd pref.FieldDescriptor) pref.Value { 178 m.checkField(fd) 179 num := fd.Number() 180 if fd.IsExtension() { 181 if fd != m.ext[num] { 182 return fd.(pref.ExtensionTypeDescriptor).Type().Zero() 183 } 184 return m.known[num] 185 } 186 if v, ok := m.known[num]; ok { 187 switch { 188 case fd.IsMap(): 189 if v.Map().Len() > 0 { 190 return v 191 } 192 case fd.IsList(): 193 if v.List().Len() > 0 { 194 return v 195 } 196 default: 197 return v 198 } 199 } 200 switch { 201 case fd.IsMap(): 202 return pref.ValueOfMap(&dynamicMap{desc: fd}) 203 case fd.IsList(): 204 return pref.ValueOfList(emptyList{desc: fd}) 205 case fd.Message() != nil: 206 return pref.ValueOfMessage(&Message{typ: messageType{fd.Message()}}) 207 case fd.Kind() == pref.BytesKind: 208 return pref.ValueOfBytes(append([]byte(nil), fd.Default().Bytes()...)) 209 default: 210 return fd.Default() 211 } 212} 213 214// Mutable returns a mutable reference to a repeated, map, or message field. 215// See protoreflect.Message for details. 216func (m *Message) Mutable(fd pref.FieldDescriptor) pref.Value { 217 m.checkField(fd) 218 if !fd.IsMap() && !fd.IsList() && fd.Message() == nil { 219 panic(errors.New("%v: getting mutable reference to non-composite type", fd.FullName())) 220 } 221 if m.known == nil { 222 panic(errors.New("%v: modification of read-only message", fd.FullName())) 223 } 224 num := fd.Number() 225 if fd.IsExtension() { 226 if fd != m.ext[num] { 227 m.ext[num] = fd 228 m.known[num] = fd.(pref.ExtensionTypeDescriptor).Type().New() 229 } 230 return m.known[num] 231 } 232 if v, ok := m.known[num]; ok { 233 return v 234 } 235 m.clearOtherOneofFields(fd) 236 m.known[num] = m.NewField(fd) 237 if fd.IsExtension() { 238 m.ext[num] = fd 239 } 240 return m.known[num] 241} 242 243// Set stores a value in a field. 244// See protoreflect.Message for details. 245func (m *Message) Set(fd pref.FieldDescriptor, v pref.Value) { 246 m.checkField(fd) 247 if m.known == nil { 248 panic(errors.New("%v: modification of read-only message", fd.FullName())) 249 } 250 if fd.IsExtension() { 251 isValid := true 252 switch { 253 case !fd.(pref.ExtensionTypeDescriptor).Type().IsValidValue(v): 254 isValid = false 255 case fd.IsList(): 256 isValid = v.List().IsValid() 257 case fd.IsMap(): 258 isValid = v.Map().IsValid() 259 case fd.Message() != nil: 260 isValid = v.Message().IsValid() 261 } 262 if !isValid { 263 panic(errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface())) 264 } 265 m.ext[fd.Number()] = fd 266 } else { 267 typecheck(fd, v) 268 } 269 m.clearOtherOneofFields(fd) 270 m.known[fd.Number()] = v 271} 272 273func (m *Message) clearOtherOneofFields(fd pref.FieldDescriptor) { 274 od := fd.ContainingOneof() 275 if od == nil { 276 return 277 } 278 num := fd.Number() 279 for i := 0; i < od.Fields().Len(); i++ { 280 if n := od.Fields().Get(i).Number(); n != num { 281 delete(m.known, n) 282 } 283 } 284} 285 286// NewField returns a new value for assignable to the field of a given descriptor. 287// See protoreflect.Message for details. 288func (m *Message) NewField(fd pref.FieldDescriptor) pref.Value { 289 m.checkField(fd) 290 switch { 291 case fd.IsExtension(): 292 return fd.(pref.ExtensionTypeDescriptor).Type().New() 293 case fd.IsMap(): 294 return pref.ValueOfMap(&dynamicMap{ 295 desc: fd, 296 mapv: make(map[interface{}]pref.Value), 297 }) 298 case fd.IsList(): 299 return pref.ValueOfList(&dynamicList{desc: fd}) 300 case fd.Message() != nil: 301 return pref.ValueOfMessage(NewMessage(fd.Message()).ProtoReflect()) 302 default: 303 return fd.Default() 304 } 305} 306 307// WhichOneof reports which field in a oneof is populated, returning nil if none are populated. 308// See protoreflect.Message for details. 309func (m *Message) WhichOneof(od pref.OneofDescriptor) pref.FieldDescriptor { 310 for i := 0; i < od.Fields().Len(); i++ { 311 fd := od.Fields().Get(i) 312 if m.Has(fd) { 313 return fd 314 } 315 } 316 return nil 317} 318 319// GetUnknown returns the raw unknown fields. 320// See protoreflect.Message for details. 321func (m *Message) GetUnknown() pref.RawFields { 322 return m.unknown 323} 324 325// SetUnknown sets the raw unknown fields. 326// See protoreflect.Message for details. 327func (m *Message) SetUnknown(r pref.RawFields) { 328 if m.known == nil { 329 panic(errors.New("%v: modification of read-only message", m.typ.desc.FullName())) 330 } 331 m.unknown = r 332} 333 334// IsValid reports whether the message is valid. 335// See protoreflect.Message for details. 336func (m *Message) IsValid() bool { 337 return m.known != nil 338} 339 340func (m *Message) checkField(fd pref.FieldDescriptor) { 341 if fd.IsExtension() && fd.ContainingMessage().FullName() == m.Descriptor().FullName() { 342 if _, ok := fd.(pref.ExtensionTypeDescriptor); !ok { 343 panic(errors.New("%v: extension field descriptor does not implement ExtensionTypeDescriptor", fd.FullName())) 344 } 345 return 346 } 347 if fd.Parent() == m.Descriptor() { 348 return 349 } 350 fields := m.Descriptor().Fields() 351 index := fd.Index() 352 if index >= fields.Len() || fields.Get(index) != fd { 353 panic(errors.New("%v: field descriptor does not belong to this message", fd.FullName())) 354 } 355} 356 357type messageType struct { 358 desc pref.MessageDescriptor 359} 360 361// NewMessageType creates a new MessageType with the provided descriptor. 362// 363// MessageTypes created by this package are equal if their descriptors are equal. 364// That is, if md1 == md2, then NewMessageType(md1) == NewMessageType(md2). 365func NewMessageType(desc pref.MessageDescriptor) pref.MessageType { 366 return messageType{desc} 367} 368 369func (mt messageType) New() pref.Message { return NewMessage(mt.desc) } 370func (mt messageType) Zero() pref.Message { return &Message{typ: messageType{mt.desc}} } 371func (mt messageType) Descriptor() pref.MessageDescriptor { return mt.desc } 372func (mt messageType) Enum(i int) pref.EnumType { 373 if ed := mt.desc.Fields().Get(i).Enum(); ed != nil { 374 return NewEnumType(ed) 375 } 376 return nil 377} 378func (mt messageType) Message(i int) pref.MessageType { 379 if md := mt.desc.Fields().Get(i).Message(); md != nil { 380 return NewMessageType(md) 381 } 382 return nil 383} 384 385type emptyList struct { 386 desc pref.FieldDescriptor 387} 388 389func (x emptyList) Len() int { return 0 } 390func (x emptyList) Get(n int) pref.Value { panic(errors.New("out of range")) } 391func (x emptyList) Set(n int, v pref.Value) { panic(errors.New("modification of immutable list")) } 392func (x emptyList) Append(v pref.Value) { panic(errors.New("modification of immutable list")) } 393func (x emptyList) AppendMutable() pref.Value { panic(errors.New("modification of immutable list")) } 394func (x emptyList) Truncate(n int) { panic(errors.New("modification of immutable list")) } 395func (x emptyList) NewElement() pref.Value { return newListEntry(x.desc) } 396func (x emptyList) IsValid() bool { return false } 397 398type dynamicList struct { 399 desc pref.FieldDescriptor 400 list []pref.Value 401} 402 403func (x *dynamicList) Len() int { 404 return len(x.list) 405} 406 407func (x *dynamicList) Get(n int) pref.Value { 408 return x.list[n] 409} 410 411func (x *dynamicList) Set(n int, v pref.Value) { 412 typecheckSingular(x.desc, v) 413 x.list[n] = v 414} 415 416func (x *dynamicList) Append(v pref.Value) { 417 typecheckSingular(x.desc, v) 418 x.list = append(x.list, v) 419} 420 421func (x *dynamicList) AppendMutable() pref.Value { 422 if x.desc.Message() == nil { 423 panic(errors.New("%v: invalid AppendMutable on list with non-message type", x.desc.FullName())) 424 } 425 v := x.NewElement() 426 x.Append(v) 427 return v 428} 429 430func (x *dynamicList) Truncate(n int) { 431 // Zero truncated elements to avoid keeping data live. 432 for i := n; i < len(x.list); i++ { 433 x.list[i] = pref.Value{} 434 } 435 x.list = x.list[:n] 436} 437 438func (x *dynamicList) NewElement() pref.Value { 439 return newListEntry(x.desc) 440} 441 442func (x *dynamicList) IsValid() bool { 443 return true 444} 445 446type dynamicMap struct { 447 desc pref.FieldDescriptor 448 mapv map[interface{}]pref.Value 449} 450 451func (x *dynamicMap) Get(k pref.MapKey) pref.Value { return x.mapv[k.Interface()] } 452func (x *dynamicMap) Set(k pref.MapKey, v pref.Value) { 453 typecheckSingular(x.desc.MapKey(), k.Value()) 454 typecheckSingular(x.desc.MapValue(), v) 455 x.mapv[k.Interface()] = v 456} 457func (x *dynamicMap) Has(k pref.MapKey) bool { return x.Get(k).IsValid() } 458func (x *dynamicMap) Clear(k pref.MapKey) { delete(x.mapv, k.Interface()) } 459func (x *dynamicMap) Mutable(k pref.MapKey) pref.Value { 460 if x.desc.MapValue().Message() == nil { 461 panic(errors.New("%v: invalid Mutable on map with non-message value type", x.desc.FullName())) 462 } 463 v := x.Get(k) 464 if !v.IsValid() { 465 v = x.NewValue() 466 x.Set(k, v) 467 } 468 return v 469} 470func (x *dynamicMap) Len() int { return len(x.mapv) } 471func (x *dynamicMap) NewValue() pref.Value { 472 if md := x.desc.MapValue().Message(); md != nil { 473 return pref.ValueOfMessage(NewMessage(md).ProtoReflect()) 474 } 475 return x.desc.MapValue().Default() 476} 477func (x *dynamicMap) IsValid() bool { 478 return x.mapv != nil 479} 480 481func (x *dynamicMap) Range(f func(pref.MapKey, pref.Value) bool) { 482 for k, v := range x.mapv { 483 if !f(pref.ValueOf(k).MapKey(), v) { 484 return 485 } 486 } 487} 488 489func isSet(fd pref.FieldDescriptor, v pref.Value) bool { 490 switch { 491 case fd.IsMap(): 492 return v.Map().Len() > 0 493 case fd.IsList(): 494 return v.List().Len() > 0 495 case fd.ContainingOneof() != nil: 496 return true 497 case fd.Syntax() == pref.Proto3 && !fd.IsExtension(): 498 switch fd.Kind() { 499 case pref.BoolKind: 500 return v.Bool() 501 case pref.EnumKind: 502 return v.Enum() != 0 503 case pref.Int32Kind, pref.Sint32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed32Kind, pref.Sfixed64Kind: 504 return v.Int() != 0 505 case pref.Uint32Kind, pref.Uint64Kind, pref.Fixed32Kind, pref.Fixed64Kind: 506 return v.Uint() != 0 507 case pref.FloatKind, pref.DoubleKind: 508 return v.Float() != 0 || math.Signbit(v.Float()) 509 case pref.StringKind: 510 return v.String() != "" 511 case pref.BytesKind: 512 return len(v.Bytes()) > 0 513 } 514 } 515 return true 516} 517 518func typecheck(fd pref.FieldDescriptor, v pref.Value) { 519 if err := typeIsValid(fd, v); err != nil { 520 panic(err) 521 } 522} 523 524func typeIsValid(fd pref.FieldDescriptor, v pref.Value) error { 525 switch { 526 case !v.IsValid(): 527 return errors.New("%v: assigning invalid value", fd.FullName()) 528 case fd.IsMap(): 529 if mapv, ok := v.Interface().(*dynamicMap); !ok || mapv.desc != fd || !mapv.IsValid() { 530 return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface()) 531 } 532 return nil 533 case fd.IsList(): 534 switch list := v.Interface().(type) { 535 case *dynamicList: 536 if list.desc == fd && list.IsValid() { 537 return nil 538 } 539 case emptyList: 540 if list.desc == fd && list.IsValid() { 541 return nil 542 } 543 } 544 return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface()) 545 default: 546 return singularTypeIsValid(fd, v) 547 } 548} 549 550func typecheckSingular(fd pref.FieldDescriptor, v pref.Value) { 551 if err := singularTypeIsValid(fd, v); err != nil { 552 panic(err) 553 } 554} 555 556func singularTypeIsValid(fd pref.FieldDescriptor, v pref.Value) error { 557 vi := v.Interface() 558 var ok bool 559 switch fd.Kind() { 560 case pref.BoolKind: 561 _, ok = vi.(bool) 562 case pref.EnumKind: 563 // We could check against the valid set of enum values, but do not. 564 _, ok = vi.(pref.EnumNumber) 565 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: 566 _, ok = vi.(int32) 567 case pref.Uint32Kind, pref.Fixed32Kind: 568 _, ok = vi.(uint32) 569 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: 570 _, ok = vi.(int64) 571 case pref.Uint64Kind, pref.Fixed64Kind: 572 _, ok = vi.(uint64) 573 case pref.FloatKind: 574 _, ok = vi.(float32) 575 case pref.DoubleKind: 576 _, ok = vi.(float64) 577 case pref.StringKind: 578 _, ok = vi.(string) 579 case pref.BytesKind: 580 _, ok = vi.([]byte) 581 case pref.MessageKind, pref.GroupKind: 582 var m pref.Message 583 m, ok = vi.(pref.Message) 584 if ok && m.Descriptor().FullName() != fd.Message().FullName() { 585 return errors.New("%v: assigning invalid message type %v", fd.FullName(), m.Descriptor().FullName()) 586 } 587 if dm, ok := vi.(*Message); ok && dm.known == nil { 588 return errors.New("%v: assigning invalid zero-value message", fd.FullName()) 589 } 590 } 591 if !ok { 592 return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface()) 593 } 594 return nil 595} 596 597func newListEntry(fd pref.FieldDescriptor) pref.Value { 598 switch fd.Kind() { 599 case pref.BoolKind: 600 return pref.ValueOfBool(false) 601 case pref.EnumKind: 602 return pref.ValueOfEnum(fd.Enum().Values().Get(0).Number()) 603 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: 604 return pref.ValueOfInt32(0) 605 case pref.Uint32Kind, pref.Fixed32Kind: 606 return pref.ValueOfUint32(0) 607 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: 608 return pref.ValueOfInt64(0) 609 case pref.Uint64Kind, pref.Fixed64Kind: 610 return pref.ValueOfUint64(0) 611 case pref.FloatKind: 612 return pref.ValueOfFloat32(0) 613 case pref.DoubleKind: 614 return pref.ValueOfFloat64(0) 615 case pref.StringKind: 616 return pref.ValueOfString("") 617 case pref.BytesKind: 618 return pref.ValueOfBytes(nil) 619 case pref.MessageKind, pref.GroupKind: 620 return pref.ValueOfMessage(NewMessage(fd.Message()).ProtoReflect()) 621 } 622 panic(errors.New("%v: unknown kind %v", fd.FullName(), fd.Kind())) 623} 624 625// NewExtensionType creates a new ExtensionType with the provided descriptor. 626// 627// Dynamic ExtensionTypes with the same descriptor compare as equal. That is, 628// if xd1 == xd2, then NewExtensionType(xd1) == NewExtensionType(xd2). 629// 630// The InterfaceOf and ValueOf methods of the extension type are defined as: 631// 632// func (xt extensionType) ValueOf(iv interface{}) protoreflect.Value { 633// return protoreflect.ValueOf(iv) 634// } 635// 636// func (xt extensionType) InterfaceOf(v protoreflect.Value) interface{} { 637// return v.Interface() 638// } 639// 640// The Go type used by the proto.GetExtension and proto.SetExtension functions 641// is determined by these methods, and is therefore equivalent to the Go type 642// used to represent a protoreflect.Value. See the protoreflect.Value 643// documentation for more details. 644func NewExtensionType(desc pref.ExtensionDescriptor) pref.ExtensionType { 645 if xt, ok := desc.(pref.ExtensionTypeDescriptor); ok { 646 desc = xt.Descriptor() 647 } 648 return extensionType{extensionTypeDescriptor{desc}} 649} 650 651func (xt extensionType) New() pref.Value { 652 switch { 653 case xt.desc.IsMap(): 654 return pref.ValueOfMap(&dynamicMap{ 655 desc: xt.desc, 656 mapv: make(map[interface{}]pref.Value), 657 }) 658 case xt.desc.IsList(): 659 return pref.ValueOfList(&dynamicList{desc: xt.desc}) 660 case xt.desc.Message() != nil: 661 return pref.ValueOfMessage(NewMessage(xt.desc.Message())) 662 default: 663 return xt.desc.Default() 664 } 665} 666 667func (xt extensionType) Zero() pref.Value { 668 switch { 669 case xt.desc.IsMap(): 670 return pref.ValueOfMap(&dynamicMap{desc: xt.desc}) 671 case xt.desc.Cardinality() == pref.Repeated: 672 return pref.ValueOfList(emptyList{desc: xt.desc}) 673 case xt.desc.Message() != nil: 674 return pref.ValueOfMessage(&Message{typ: messageType{xt.desc.Message()}}) 675 default: 676 return xt.desc.Default() 677 } 678} 679 680func (xt extensionType) TypeDescriptor() pref.ExtensionTypeDescriptor { 681 return xt.desc 682} 683 684func (xt extensionType) ValueOf(iv interface{}) pref.Value { 685 v := pref.ValueOf(iv) 686 typecheck(xt.desc, v) 687 return v 688} 689 690func (xt extensionType) InterfaceOf(v pref.Value) interface{} { 691 typecheck(xt.desc, v) 692 return v.Interface() 693} 694 695func (xt extensionType) IsValidInterface(iv interface{}) bool { 696 return typeIsValid(xt.desc, pref.ValueOf(iv)) == nil 697} 698 699func (xt extensionType) IsValidValue(v pref.Value) bool { 700 return typeIsValid(xt.desc, v) == nil 701} 702 703type extensionTypeDescriptor struct { 704 pref.ExtensionDescriptor 705} 706 707func (xt extensionTypeDescriptor) Type() pref.ExtensionType { 708 return extensionType{xt} 709} 710 711func (xt extensionTypeDescriptor) Descriptor() pref.ExtensionDescriptor { 712 return xt.ExtensionDescriptor 713} 714