diff options
Diffstat (limited to 'src/csharp/Grpc.Reflection/SymbolRegistry.cs')
-rw-r--r-- | src/csharp/Grpc.Reflection/SymbolRegistry.cs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/csharp/Grpc.Reflection/SymbolRegistry.cs b/src/csharp/Grpc.Reflection/SymbolRegistry.cs new file mode 100644 index 0000000000..b7104ab2f9 --- /dev/null +++ b/src/csharp/Grpc.Reflection/SymbolRegistry.cs @@ -0,0 +1,160 @@ +#region Copyright notice and license +// Copyright 2015, Google Inc. +// All rights reserved. +// +// 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. +#endregion + +using System.Collections.Generic; +using Grpc.Core.Utils; +using Google.Protobuf.Reflection; + +namespace Grpc.Reflection +{ + /// <summary>Registry of protobuf symbols</summary> + public class SymbolRegistry + { + private readonly Dictionary<string, FileDescriptor> filesByName; + private readonly Dictionary<string, FileDescriptor> filesBySymbol; + + private SymbolRegistry(Dictionary<string, FileDescriptor> filesByName, Dictionary<string, FileDescriptor> filesBySymbol) + { + this.filesByName = new Dictionary<string, FileDescriptor>(filesByName); + this.filesBySymbol = new Dictionary<string, FileDescriptor>(filesBySymbol); + } + + /// <summary> + /// Creates a symbol registry from the specified set of file descriptors. + /// </summary> + /// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param> + /// <returns>A symbol registry for the given files.</returns> + public static SymbolRegistry FromFiles(IEnumerable<FileDescriptor> fileDescriptors) + { + GrpcPreconditions.CheckNotNull(fileDescriptors); + var builder = new Builder(); + foreach (var file in fileDescriptors) + { + builder.AddFile(file); + } + return builder.Build(); + } + + /// <summary> + /// Gets file descriptor for given file name (including package path). Returns <c>null</c> if not found. + /// </summary> + public FileDescriptor FileByName(string filename) + { + FileDescriptor file; + filesByName.TryGetValue(filename, out file); + return file; + } + + /// <summary> + /// Gets file descriptor that contains definition of given symbol full name (including package path). Returns <c>null</c> if not found. + /// </summary> + public FileDescriptor FileContainingSymbol(string symbol) + { + FileDescriptor file; + filesBySymbol.TryGetValue(symbol, out file); + return file; + } + + /// <summary> + /// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. + /// </summary> + private class Builder + { + private readonly Dictionary<string, FileDescriptor> filesByName; + private readonly Dictionary<string, FileDescriptor> filesBySymbol; + + + internal Builder() + { + filesByName = new Dictionary<string, FileDescriptor>(); + filesBySymbol = new Dictionary<string, FileDescriptor>(); + } + + internal void AddFile(FileDescriptor fileDescriptor) + { + if (filesByName.ContainsKey(fileDescriptor.Name)) + { + return; + } + filesByName.Add(fileDescriptor.Name, fileDescriptor); + + foreach (var dependency in fileDescriptor.Dependencies) + { + AddFile(dependency); + } + foreach (var enumeration in fileDescriptor.EnumTypes) + { + AddEnum(enumeration); + } + foreach (var message in fileDescriptor.MessageTypes) + { + AddMessage(message); + } + foreach (var service in fileDescriptor.Services) + { + AddService(service); + } + } + + private void AddEnum(EnumDescriptor enumDescriptor) + { + filesBySymbol[enumDescriptor.FullName] = enumDescriptor.File; + } + + private void AddMessage(MessageDescriptor messageDescriptor) + { + foreach (var nestedEnum in messageDescriptor.EnumTypes) + { + AddEnum(nestedEnum); + } + foreach (var nestedType in messageDescriptor.NestedTypes) + { + AddMessage(nestedType); + } + filesBySymbol[messageDescriptor.FullName] = messageDescriptor.File; + } + + private void AddService(ServiceDescriptor serviceDescriptor) + { + foreach (var method in serviceDescriptor.Methods) + { + filesBySymbol[method.FullName] = method.File; + } + filesBySymbol[serviceDescriptor.FullName] = serviceDescriptor.File; + } + + internal SymbolRegistry Build() + { + return new SymbolRegistry(filesByName, filesBySymbol); + } + } + } +} |