You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
17 KiB
379 lines
17 KiB
#Region "Microsoft.VisualBasic::fc1d43ebd0b04c717a5668f0dc44bf61, Google.Protobuf\Reflection\Descriptor\FileDescriptor.vb"
|
|
|
|
' Author:
|
|
'
|
|
' asuka (amethyst.asuka@gcmodeller.org)
|
|
' xie (genetics@smrucc.org)
|
|
' xieguigang (xie.guigang@live.com)
|
|
'
|
|
' Copyright (c) 2018 GPL3 Licensed
|
|
'
|
|
'
|
|
' GNU GENERAL PUBLIC LICENSE (GPL3)
|
|
'
|
|
'
|
|
' This program is free software: you can redistribute it and/or modify
|
|
' it under the terms of the GNU General Public License as published by
|
|
' the Free Software Foundation, either version 3 of the License, or
|
|
' (at your option) any later version.
|
|
'
|
|
' This program is distributed in the hope that it will be useful,
|
|
' but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
' GNU General Public License for more details.
|
|
'
|
|
' You should have received a copy of the GNU General Public License
|
|
' along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
' /********************************************************************************/
|
|
|
|
' Summaries:
|
|
|
|
' Class FileDescriptor
|
|
'
|
|
' Properties: Dependencies, DescriptorPool, DescriptorProtoFileDescriptor, EnumTypes, File
|
|
' FullName, MessageTypes, Name, Package, Proto
|
|
' PublicDependencies, SerializedData, Services
|
|
'
|
|
' Constructor: (+1 Overloads) Sub New
|
|
'
|
|
' Function: BuildFrom, ComputeFullName, DeterminePublicDependencies, FindTypeByName, FromGeneratedCode
|
|
' ToString
|
|
'
|
|
' Sub: CrossLink
|
|
'
|
|
'
|
|
' /********************************************************************************/
|
|
|
|
#End Region
|
|
|
|
#Region "Copyright notice and license"
|
|
' Protocol Buffers - Google's data interchange format
|
|
' Copyright 2008 Google Inc. All rights reserved.
|
|
' https://developers.google.com/protocol-buffers/
|
|
'
|
|
' Redistribution and use in source and binary forms, with or without
|
|
' modification, are permitted provided that the following conditions are
|
|
' met:
|
|
'
|
|
' * Redistributions of source code must retain the above copyright
|
|
' notice, this list of conditions and the following disclaimer.
|
|
' * Redistributions in binary form must reproduce the above
|
|
' copyright notice, this list of conditions and the following disclaimer
|
|
' in the documentation and/or other materials provided with the
|
|
' distribution.
|
|
' * Neither the name of Google Inc. nor the names of its
|
|
' contributors may be used to endorse or promote products derived from
|
|
' this software without specific prior written permission.
|
|
'
|
|
' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
' "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
' LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
' A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
' OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
' SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
' LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
' DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
' THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
' (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
' OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#End Region
|
|
|
|
Imports System
|
|
Imports System.Collections.Generic
|
|
Imports System.Collections.ObjectModel
|
|
|
|
Namespace Google.Protobuf.Reflection
|
|
''' <summary>
|
|
''' Describes a .proto file, including everything defined within.
|
|
''' IDescriptor is implemented such that the File property returns this descriptor,
|
|
''' and the FullName is the same as the Name.
|
|
''' </summary>
|
|
Public NotInheritable Class FileDescriptor
|
|
Implements IDescriptor
|
|
|
|
Private Sub New(descriptorData As ByteString, proto As FileDescriptorProto, dependencies As FileDescriptor(), pool As DescriptorPool, allowUnknownDependencies As Boolean, generatedCodeInfo As GeneratedClrTypeInfo)
|
|
SerializedData = descriptorData
|
|
DescriptorPool = pool
|
|
Me.Proto = proto
|
|
Me.Dependencies = New ReadOnlyCollection(Of FileDescriptor)(CType(dependencies.Clone(), FileDescriptor()))
|
|
PublicDependencies = DeterminePublicDependencies(Me, proto, dependencies, allowUnknownDependencies)
|
|
pool.AddPackage(Package, Me)
|
|
MessageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType, Function(message, index) New MessageDescriptor(message, Me, Nothing, index, generatedCodeInfo.NestedTypes(index)))
|
|
EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, Function(enumType, index) New EnumDescriptor(enumType, Me, Nothing, index, generatedCodeInfo.NestedEnums(index)))
|
|
Services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service, Function(service, index) New ServiceDescriptor(service, Me, index))
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Computes the full name of a descriptor within this file, with an optional parent message.
|
|
''' </summary>
|
|
Friend Function ComputeFullName(parent As MessageDescriptor, name As String) As String
|
|
If parent IsNot Nothing Then
|
|
Return parent.FullName & "." & name
|
|
End If
|
|
|
|
If Package.Length > 0 Then
|
|
Return Package & "." & name
|
|
End If
|
|
|
|
Return name
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Extracts public dependencies from direct dependencies. This is a static method despite its
|
|
''' first parameter, as the value we're in the middle of constructing is only used for exceptions.
|
|
''' </summary>
|
|
Private Shared Function DeterminePublicDependencies(this As FileDescriptor, proto As FileDescriptorProto, dependencies As FileDescriptor(), allowUnknownDependencies As Boolean) As IList(Of FileDescriptor)
|
|
Dim nameToFileMap = New Dictionary(Of String, FileDescriptor)()
|
|
|
|
For Each file As FileDescriptor In dependencies
|
|
nameToFileMap(file.Name) = file
|
|
Next
|
|
|
|
Dim publicDependencies = New List(Of FileDescriptor)()
|
|
|
|
For i = 0 To proto.PublicDependency.Count - 1
|
|
Dim index = proto.PublicDependency(i)
|
|
|
|
If index < 0 OrElse index >= proto.Dependency.Count Then
|
|
Throw New DescriptorValidationException(this, "Invalid public dependency index.")
|
|
End If
|
|
|
|
Dim name = proto.Dependency(index)
|
|
Dim file = nameToFileMap(name)
|
|
|
|
If file Is Nothing Then
|
|
If Not allowUnknownDependencies Then
|
|
Throw New DescriptorValidationException(this, "Invalid public dependency: " & name)
|
|
' Ignore unknown dependencies.
|
|
End If
|
|
Else
|
|
publicDependencies.Add(file)
|
|
End If
|
|
Next
|
|
|
|
Return New ReadOnlyCollection(Of FileDescriptor)(publicDependencies)
|
|
End Function
|
|
|
|
''' <value>
|
|
''' The descriptor in its protocol message representation.
|
|
''' </value>
|
|
Friend ReadOnly Property Proto As FileDescriptorProto
|
|
|
|
''' <value>
|
|
''' The file name.
|
|
''' </value>
|
|
Public ReadOnly Property Name As String Implements IDescriptor.Name
|
|
Get
|
|
Return Proto.Name
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' The package as declared in the .proto file. This may or may not
|
|
''' be equivalent to the .NET namespace of the generated classes.
|
|
''' </summary>
|
|
Public ReadOnly Property Package As String
|
|
Get
|
|
Return Proto.Package
|
|
End Get
|
|
End Property
|
|
|
|
''' <value>
|
|
''' Unmodifiable list of top-level message types declared in this file.
|
|
''' </value>
|
|
Public ReadOnly Property MessageTypes As IList(Of MessageDescriptor)
|
|
|
|
''' <value>
|
|
''' Unmodifiable list of top-level enum types declared in this file.
|
|
''' </value>
|
|
Public ReadOnly Property EnumTypes As IList(Of EnumDescriptor)
|
|
|
|
''' <value>
|
|
''' Unmodifiable list of top-level services declared in this file.
|
|
''' </value>
|
|
Public ReadOnly Property Services As IList(Of ServiceDescriptor)
|
|
|
|
''' <value>
|
|
''' Unmodifiable list of this file's dependencies (imports).
|
|
''' </value>
|
|
Public ReadOnly Property Dependencies As IList(Of FileDescriptor)
|
|
|
|
''' <value>
|
|
''' Unmodifiable list of this file's public dependencies (public imports).
|
|
''' </value>
|
|
Public ReadOnly Property PublicDependencies As IList(Of FileDescriptor)
|
|
|
|
''' <value>
|
|
''' The original serialized binary form of this descriptor.
|
|
''' </value>
|
|
Public ReadOnly Property SerializedData As ByteString
|
|
|
|
''' <value>
|
|
''' Implementation of IDescriptor.FullName - just returns the same as Name.
|
|
''' </value>
|
|
Private ReadOnly Property FullName As String Implements IDescriptor.FullName
|
|
Get
|
|
Return Name
|
|
End Get
|
|
End Property
|
|
|
|
''' <value>
|
|
''' Implementation of IDescriptor.File - just returns this descriptor.
|
|
''' </value>
|
|
Private ReadOnly Property File As FileDescriptor Implements IDescriptor.File
|
|
Get
|
|
Return Me
|
|
End Get
|
|
End Property
|
|
|
|
''' <value>
|
|
''' Pool containing symbol descriptors.
|
|
''' </value>
|
|
Friend ReadOnly Property DescriptorPool As DescriptorPool
|
|
|
|
''' <summary>
|
|
''' Finds a type (message, enum, service or extension) in the file by name. Does not find nested types.
|
|
''' </summary>
|
|
''' <param name="name">The unqualified type name to look for.</param>
|
|
''' <typeparam name="T">The type of descriptor to look for</typeparam>
|
|
''' <returns>The type's descriptor, or null if not found.</returns>
|
|
Public Function FindTypeByName(Of T As {Class, IDescriptor})(name As String) As T
|
|
' Don't allow looking up nested types. This will make optimization
|
|
' easier later.
|
|
If name.IndexOf("."c) <> -1 Then
|
|
Return Nothing
|
|
End If
|
|
|
|
If Package.Length > 0 Then
|
|
name = Package & "." & name
|
|
End If
|
|
|
|
Dim result = DescriptorPool.FindSymbol(Of T)(name)
|
|
|
|
If result IsNot Nothing AndAlso result.File Is Me Then
|
|
Return result
|
|
End If
|
|
|
|
Return Nothing
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Builds a FileDescriptor from its protocol buffer representation.
|
|
''' </summary>
|
|
''' <param name="descriptorData">The original serialized descriptor data.
|
|
''' We have only limited proto2 support, so serializing FileDescriptorProto
|
|
''' would not necessarily give us this.</param>
|
|
''' <param name="proto">The protocol message form of the FileDescriptor.</param>
|
|
''' <param name="dependencies">FileDescriptors corresponding to all of the
|
|
''' file's dependencies, in the exact order listed in the .proto file. May be null,
|
|
''' in which case it is treated as an empty array.</param>
|
|
''' <param name="allowUnknownDependencies">Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false).</param>
|
|
''' <param name="generatedCodeInfo">Details about generated code, for the purposes of reflection.</param>
|
|
''' <exception cref="DescriptorValidationException">If <paramrefname="proto"/> is not
|
|
''' a valid descriptor. This can occur for a number of reasons, such as a field
|
|
''' having an undefined type or because two messages were defined with the same name.</exception>
|
|
Private Shared Function BuildFrom(descriptorData As ByteString, proto As FileDescriptorProto, dependencies As FileDescriptor(), allowUnknownDependencies As Boolean, generatedCodeInfo As GeneratedClrTypeInfo) As FileDescriptor
|
|
' Building descriptors involves two steps: translating and linking.
|
|
' In the translation step (implemented by FileDescriptor's
|
|
' constructor), we build an object tree mirroring the
|
|
' FileDescriptorProto's tree and put all of the descriptors into the
|
|
' DescriptorPool's lookup tables. In the linking step, we look up all
|
|
' type references in the DescriptorPool, so that, for example, a
|
|
' FieldDescriptor for an embedded message contains a pointer directly
|
|
' to the Descriptor for that message's type. We also detect undefined
|
|
' types in the linking step.
|
|
If dependencies Is Nothing Then
|
|
dependencies = New FileDescriptor(-1) {}
|
|
End If
|
|
|
|
Dim pool As DescriptorPool = New DescriptorPool(dependencies)
|
|
Dim result As FileDescriptor = New FileDescriptor(descriptorData, proto, dependencies, pool, allowUnknownDependencies, generatedCodeInfo)
|
|
|
|
' Validate that the dependencies we've been passed (as FileDescriptors) are actually the ones we
|
|
' need.
|
|
If dependencies.Length <> proto.Dependency.Count Then
|
|
Throw New DescriptorValidationException(result, "Dependencies passed to FileDescriptor.BuildFrom() don't match " & "those listed in the FileDescriptorProto.")
|
|
End If
|
|
|
|
For i = 0 To proto.Dependency.Count - 1
|
|
|
|
If Not Equals(dependencies(i).Name, proto.Dependency(i)) Then
|
|
Throw New DescriptorValidationException(result, "Dependencies passed to FileDescriptor.BuildFrom() don't match " & "those listed in the FileDescriptorProto. Expected: " & proto.Dependency(i) & " but was: " & dependencies(i).Name)
|
|
End If
|
|
Next
|
|
|
|
result.CrossLink()
|
|
Return result
|
|
End Function
|
|
|
|
Private Sub CrossLink()
|
|
For Each message In MessageTypes
|
|
message.CrossLink()
|
|
Next
|
|
|
|
For Each service In Services
|
|
service.CrossLink()
|
|
Next
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Creates a descriptor for generated code.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' This method is only designed to be used by the results of generating code with protoc,
|
|
''' which creates the appropriate dependencies etc. It has to be public because the generated
|
|
''' code is "external", but should not be called directly by end users.
|
|
''' </remarks>
|
|
Public Shared Function FromGeneratedCode(descriptorData As Byte(), dependencies As FileDescriptor(), generatedCodeInfo As GeneratedClrTypeInfo) As FileDescriptor
|
|
Dim proto As FileDescriptorProto
|
|
|
|
Try
|
|
proto = FileDescriptorProto.Parser.ParseFrom(descriptorData)
|
|
Catch e As InvalidProtocolBufferException
|
|
Throw New ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e)
|
|
End Try
|
|
|
|
Try
|
|
' When building descriptors for generated code, we allow unknown
|
|
' dependencies by default.
|
|
Return BuildFrom(ByteString.CopyFrom(descriptorData), proto, dependencies, True, generatedCodeInfo)
|
|
Catch e As DescriptorValidationException
|
|
Throw New ArgumentException($"Invalid embedded descriptor for ""{proto.Name}"".", e)
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a <see cref="System.String"/> that represents this instance.
|
|
''' </summary>
|
|
''' <returns>
|
|
''' A <see cref="System.String"/> that represents this instance.
|
|
''' </returns>
|
|
Public Overrides Function ToString() As String
|
|
Return $"FileDescriptor for {Name}"
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns the file descriptor for descriptor.proto.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' This is used for protos which take a direct dependency on <c>descriptor.proto</c>, typically for
|
|
''' annotations. While <c>descriptor.proto</c> is a proto2 file, it is built into the Google.Protobuf
|
|
''' runtime for reflection purposes. The messages are internal to the runtime as they would require
|
|
''' proto2 semantics for full support, but the file descriptor is available via this property. The
|
|
''' C# codegen in protoc automatically uses this property when it detects a dependency on <c>descriptor.proto</c>.
|
|
''' </remarks>
|
|
''' <value>
|
|
''' The file descriptor for <c>descriptor.proto</c>.
|
|
''' </value>
|
|
Public Shared ReadOnly Property DescriptorProtoFileDescriptor As FileDescriptor
|
|
Get
|
|
Return Descriptor
|
|
End Get
|
|
End Property
|
|
End Class
|
|
End Namespace
|
|
|