blob: 76e0b01d6b10debedf5cc6871c233c7319ee91a2 [file] [log] [blame]
Jan Tattermusch02017762016-11-23 15:39:56 +01001#region Copyright notice and license
Jan Tattermusch7897ae92017-06-07 22:57:36 +02002// Copyright 2015 gRPC authors.
Jan Tattermusch02017762016-11-23 15:39:56 +01003//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02004// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
Jan Tattermusch02017762016-11-23 15:39:56 +01007//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02008// http://www.apache.org/licenses/LICENSE-2.0
Jan Tattermusch02017762016-11-23 15:39:56 +01009//
Jan Tattermusch7897ae92017-06-07 22:57:36 +020010// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
Jan Tattermusch02017762016-11-23 15:39:56 +010015#endregion
16
17using System.Collections.Generic;
18using Grpc.Core.Utils;
19using Google.Protobuf.Reflection;
20
21namespace Grpc.Reflection
22{
23 /// <summary>Registry of protobuf symbols</summary>
24 public class SymbolRegistry
25 {
26 private readonly Dictionary<string, FileDescriptor> filesByName;
27 private readonly Dictionary<string, FileDescriptor> filesBySymbol;
28
29 private SymbolRegistry(Dictionary<string, FileDescriptor> filesByName, Dictionary<string, FileDescriptor> filesBySymbol)
30 {
31 this.filesByName = new Dictionary<string, FileDescriptor>(filesByName);
32 this.filesBySymbol = new Dictionary<string, FileDescriptor>(filesBySymbol);
33 }
34
35 /// <summary>
36 /// Creates a symbol registry from the specified set of file descriptors.
37 /// </summary>
38 /// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param>
39 /// <returns>A symbol registry for the given files.</returns>
40 public static SymbolRegistry FromFiles(IEnumerable<FileDescriptor> fileDescriptors)
41 {
42 GrpcPreconditions.CheckNotNull(fileDescriptors);
43 var builder = new Builder();
44 foreach (var file in fileDescriptors)
45 {
46 builder.AddFile(file);
47 }
48 return builder.Build();
49 }
50
51 /// <summary>
52 /// Gets file descriptor for given file name (including package path). Returns <c>null</c> if not found.
53 /// </summary>
54 public FileDescriptor FileByName(string filename)
55 {
56 FileDescriptor file;
57 filesByName.TryGetValue(filename, out file);
58 return file;
59 }
60
61 /// <summary>
62 /// Gets file descriptor that contains definition of given symbol full name (including package path). Returns <c>null</c> if not found.
63 /// </summary>
64 public FileDescriptor FileContainingSymbol(string symbol)
65 {
66 FileDescriptor file;
67 filesBySymbol.TryGetValue(symbol, out file);
68 return file;
69 }
70
71 /// <summary>
72 /// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls.
73 /// </summary>
74 private class Builder
75 {
76 private readonly Dictionary<string, FileDescriptor> filesByName;
77 private readonly Dictionary<string, FileDescriptor> filesBySymbol;
78
79
80 internal Builder()
81 {
82 filesByName = new Dictionary<string, FileDescriptor>();
83 filesBySymbol = new Dictionary<string, FileDescriptor>();
84 }
85
86 internal void AddFile(FileDescriptor fileDescriptor)
87 {
88 if (filesByName.ContainsKey(fileDescriptor.Name))
89 {
90 return;
91 }
92 filesByName.Add(fileDescriptor.Name, fileDescriptor);
93
94 foreach (var dependency in fileDescriptor.Dependencies)
95 {
96 AddFile(dependency);
97 }
98 foreach (var enumeration in fileDescriptor.EnumTypes)
99 {
100 AddEnum(enumeration);
101 }
102 foreach (var message in fileDescriptor.MessageTypes)
103 {
104 AddMessage(message);
105 }
106 foreach (var service in fileDescriptor.Services)
107 {
108 AddService(service);
109 }
110 }
111
112 private void AddEnum(EnumDescriptor enumDescriptor)
113 {
114 filesBySymbol[enumDescriptor.FullName] = enumDescriptor.File;
115 }
116
117 private void AddMessage(MessageDescriptor messageDescriptor)
118 {
119 foreach (var nestedEnum in messageDescriptor.EnumTypes)
120 {
121 AddEnum(nestedEnum);
122 }
123 foreach (var nestedType in messageDescriptor.NestedTypes)
124 {
125 AddMessage(nestedType);
126 }
127 filesBySymbol[messageDescriptor.FullName] = messageDescriptor.File;
128 }
129
130 private void AddService(ServiceDescriptor serviceDescriptor)
131 {
132 foreach (var method in serviceDescriptor.Methods)
133 {
134 filesBySymbol[method.FullName] = method.File;
135 }
136 filesBySymbol[serviceDescriptor.FullName] = serviceDescriptor.File;
137 }
138
139 internal SymbolRegistry Build()
140 {
141 return new SymbolRegistry(filesByName, filesBySymbol);
142 }
143 }
144 }
145}