diff options
Diffstat (limited to 'src/ProtocolBuffers/Descriptors')
17 files changed, 2829 insertions, 2451 deletions
diff --git a/src/ProtocolBuffers/Descriptors/DescriptorBase.cs b/src/ProtocolBuffers/Descriptors/DescriptorBase.cs index 1f4d6651..59006f80 100644 --- a/src/ProtocolBuffers/Descriptors/DescriptorBase.cs +++ b/src/ProtocolBuffers/Descriptors/DescriptorBase.cs @@ -1,103 +1,115 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Base class for nearly all descriptors, providing common functionality. - /// </summary> - /// <typeparam name="TProto">Type of the protocol buffer form of this descriptor</typeparam> - /// <typeparam name="TOptions">Type of the options protocol buffer for this descriptor</typeparam> - public abstract class DescriptorBase<TProto, TOptions> : IDescriptor<TProto> - where TProto : IMessage, IDescriptorProto<TOptions> { - - private TProto proto; - private readonly FileDescriptor file; - private readonly string fullName; - - protected DescriptorBase(TProto proto, FileDescriptor file, string fullName) { - this.proto = proto; - this.file = file; - this.fullName = fullName; - } - - internal virtual void ReplaceProto(TProto newProto) { - this.proto = newProto; - } - - protected static string ComputeFullName(FileDescriptor file, MessageDescriptor parent, string name) { - if (parent != null) { - return parent.FullName + "." + name; - } - if (file.Package.Length > 0) { - return file.Package + "." + name; - } - return name; - } - - IMessage IDescriptor.Proto { - get { return proto; } - } - - /// <summary> - /// Returns the protocol buffer form of this descriptor. - /// </summary> - public TProto Proto { - get { return proto; } - } - - public TOptions Options { - get { return proto.Options; } - } - - /// <summary> - /// The fully qualified name of the descriptor's target. - /// </summary> - public string FullName { - get { return fullName; } - } - - /// <summary> - /// The brief name of the descriptor's target. - /// </summary> - public string Name { - get { return proto.Name; } - } - - /// <value> - /// The file this descriptor was declared in. - /// </value> - public FileDescriptor File { - get { return file; } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Base class for nearly all descriptors, providing common functionality.
+ /// </summary>
+ /// <typeparam name="TProto">Type of the protocol buffer form of this descriptor</typeparam>
+ /// <typeparam name="TOptions">Type of the options protocol buffer for this descriptor</typeparam>
+ public abstract class DescriptorBase<TProto, TOptions> : IDescriptor<TProto>
+ where TProto : IMessage, IDescriptorProto<TOptions>
+ {
+ private TProto proto;
+ private readonly FileDescriptor file;
+ private readonly string fullName;
+
+ protected DescriptorBase(TProto proto, FileDescriptor file, string fullName)
+ {
+ this.proto = proto;
+ this.file = file;
+ this.fullName = fullName;
+ }
+
+ internal virtual void ReplaceProto(TProto newProto)
+ {
+ this.proto = newProto;
+ }
+
+ protected static string ComputeFullName(FileDescriptor file, MessageDescriptor parent, string name)
+ {
+ if (parent != null)
+ {
+ return parent.FullName + "." + name;
+ }
+ if (file.Package.Length > 0)
+ {
+ return file.Package + "." + name;
+ }
+ return name;
+ }
+
+ IMessage IDescriptor.Proto
+ {
+ get { return proto; }
+ }
+
+ /// <summary>
+ /// Returns the protocol buffer form of this descriptor.
+ /// </summary>
+ public TProto Proto
+ {
+ get { return proto; }
+ }
+
+ public TOptions Options
+ {
+ get { return proto.Options; }
+ }
+
+ /// <summary>
+ /// The fully qualified name of the descriptor's target.
+ /// </summary>
+ public string FullName
+ {
+ get { return fullName; }
+ }
+
+ /// <summary>
+ /// The brief name of the descriptor's target.
+ /// </summary>
+ public string Name
+ {
+ get { return proto.Name; }
+ }
+
+ /// <value>
+ /// The file this descriptor was declared in.
+ /// </value>
+ public FileDescriptor File
+ {
+ get { return file; }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/DescriptorPool.cs b/src/ProtocolBuffers/Descriptors/DescriptorPool.cs index c8654572..12abafeb 100644 --- a/src/ProtocolBuffers/Descriptors/DescriptorPool.cs +++ b/src/ProtocolBuffers/Descriptors/DescriptorPool.cs @@ -1,296 +1,352 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System.Collections.Generic; -using System; -using System.Text; -using System.Text.RegularExpressions; - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Contains lookup tables containing all the descriptors defined in a particular file. - /// </summary> - internal sealed class DescriptorPool { - - private readonly IDictionary<string, IDescriptor> descriptorsByName = - new Dictionary<string, IDescriptor>(); - private readonly IDictionary<DescriptorIntPair, FieldDescriptor> fieldsByNumber = - new Dictionary<DescriptorIntPair, FieldDescriptor>(); - private readonly IDictionary<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = - new Dictionary<DescriptorIntPair, EnumValueDescriptor>(); - private readonly DescriptorPool[] dependencies; - - internal DescriptorPool(FileDescriptor[] dependencyFiles) { - dependencies = new DescriptorPool[dependencyFiles.Length]; - for (int i = 0; i < dependencyFiles.Length; i++) { - dependencies[i] = dependencyFiles[i].DescriptorPool; - } - - foreach (FileDescriptor dependency in dependencyFiles) { - AddPackage(dependency.Package, dependency); - } - } - - /// <summary> - /// Finds a symbol of the given name within the pool. - /// </summary> - /// <typeparam name="T">The type of symbol to look for</typeparam> - /// <param name="fullName">Fully-qualified name to look up</param> - /// <returns>The symbol with the given name and type, - /// or null if the symbol doesn't exist or has the wrong type</returns> - internal T FindSymbol<T>(string fullName) where T : class, IDescriptor { - IDescriptor result; - descriptorsByName.TryGetValue(fullName, out result); - T descriptor = result as T; - if (descriptor != null) { - return descriptor; - } - - foreach (DescriptorPool dependency in dependencies) { - dependency.descriptorsByName.TryGetValue(fullName, out result); - descriptor = result as T; - if (descriptor != null) { - return descriptor; - } - } - - return null; - } - - /// <summary> - /// Adds a package to the symbol tables. If a package by the same name - /// already exists, that is fine, but if some other kind of symbol - /// exists under the same name, an exception is thrown. If the package - /// has multiple components, this also adds the parent package(s). - /// </summary> - internal void AddPackage(string fullName, FileDescriptor file) { - int dotpos = fullName.LastIndexOf('.'); - String name; - if (dotpos != -1) { - AddPackage(fullName.Substring(0, dotpos), file); - name = fullName.Substring(dotpos + 1); - } else { - name = fullName; - } - - IDescriptor old; - if (descriptorsByName.TryGetValue(fullName, out old)) { - if (!(old is PackageDescriptor)) { - throw new DescriptorValidationException(file, - "\"" + name + "\" is already defined (as something other than a " + - "package) in file \"" + old.File.Name + "\"."); - } - } - descriptorsByName[fullName] = new PackageDescriptor(name, fullName, file); - } - - /// <summary> - /// Adds a symbol to the symbol table. - /// </summary> - /// <exception cref="DescriptorValidationException">The symbol already existed - /// in the symbol table.</exception> - internal void AddSymbol(IDescriptor descriptor) { - ValidateSymbolName(descriptor); - String fullName = descriptor.FullName; - - IDescriptor old; - if (descriptorsByName.TryGetValue(fullName, out old)) { - int dotPos = fullName.LastIndexOf('.'); - string message; - if (descriptor.File == old.File) { - if (dotPos == -1) { - message = "\"" + fullName + "\" is already defined."; - } else { - message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" + fullName.Substring(0, dotPos) + "\"."; - } - } else { - message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\"."; - } - throw new DescriptorValidationException(descriptor, message); - } - descriptorsByName[fullName] = descriptor; - } - - private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$", SilverlightCompatibility.CompiledRegexWhereAvailable); - - /// <summary> - /// Verifies that the descriptor's name is valid (i.e. it contains - /// only letters, digits and underscores, and does not start with a digit). - /// </summary> - /// <param name="descriptor"></param> - private static void ValidateSymbolName(IDescriptor descriptor) { - if (descriptor.Name == "") { - throw new DescriptorValidationException(descriptor, "Missing name."); - } - if (!ValidationRegex.IsMatch(descriptor.Name)) { - throw new DescriptorValidationException(descriptor, - "\"" + descriptor.Name + "\" is not a valid identifier."); - } - } - - /// <summary> - /// Returns the field with the given number in the given descriptor, - /// or null if it can't be found. - /// </summary> - internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number) { - FieldDescriptor ret; - fieldsByNumber.TryGetValue(new DescriptorIntPair(messageDescriptor, number), out ret); - return ret; - } - - internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number) { - EnumValueDescriptor ret; - enumValuesByNumber.TryGetValue(new DescriptorIntPair(enumDescriptor, number), out ret); - return ret; - } - - /// <summary> - /// Adds a field to the fieldsByNumber table. - /// </summary> - /// <exception cref="DescriptorValidationException">A field with the same - /// containing type and number already exists.</exception> - internal void AddFieldByNumber(FieldDescriptor field) { - DescriptorIntPair key = new DescriptorIntPair(field.ContainingType, field.FieldNumber); - FieldDescriptor old; - if (fieldsByNumber.TryGetValue(key, out old)) { - throw new DescriptorValidationException(field, "Field number " + field.FieldNumber + - "has already been used in \"" + field.ContainingType.FullName + - "\" by field \"" + old.Name + "\"."); - } - fieldsByNumber[key] = field; - } - - /// <summary> - /// Adds an enum value to the enumValuesByNumber table. If an enum value - /// with the same type and number already exists, this method does nothing. - /// (This is allowed; the first value defined with the number takes precedence.) - /// </summary> - internal void AddEnumValueByNumber(EnumValueDescriptor enumValue) { - DescriptorIntPair key = new DescriptorIntPair(enumValue.EnumDescriptor, enumValue.Number); - if (!enumValuesByNumber.ContainsKey(key)) { - enumValuesByNumber[key] = enumValue; - } - } - - /// <summary> - /// Looks up a descriptor by name, relative to some other descriptor. - /// The name may be fully-qualified (with a leading '.'), partially-qualified, - /// or unqualified. C++-like name lookup semantics are used to search for the - /// matching descriptor. - /// </summary> - public IDescriptor LookupSymbol(string name, IDescriptor relativeTo) { - // TODO(jonskeet): This could be optimized in a number of ways. - - IDescriptor result; - if (name.StartsWith(".")) { - // Fully-qualified name. - result = FindSymbol<IDescriptor>(name.Substring(1)); - } else { - // If "name" is a compound identifier, we want to search for the - // first component of it, then search within it for the rest. - int firstPartLength = name.IndexOf('.'); - string firstPart = firstPartLength == -1 ? name : name.Substring(0, firstPartLength); - - // We will search each parent scope of "relativeTo" looking for the - // symbol. - StringBuilder scopeToTry = new StringBuilder(relativeTo.FullName); - - while (true) { - // Chop off the last component of the scope. - - // TODO(jonskeet): Make this more efficient. May not be worth using StringBuilder at all - int dotpos = scopeToTry.ToString().LastIndexOf("."); - if (dotpos == -1) { - result = FindSymbol<IDescriptor>(name); - break; - } else { - scopeToTry.Length = dotpos + 1; - - // Append firstPart and try to find. - scopeToTry.Append(firstPart); - result = FindSymbol<IDescriptor>(scopeToTry.ToString()); - - if (result != null) { - if (firstPartLength != -1) { - // We only found the first part of the symbol. Now look for - // the whole thing. If this fails, we *don't* want to keep - // searching parent scopes. - scopeToTry.Length = dotpos + 1; - scopeToTry.Append(name); - result = FindSymbol<IDescriptor>(scopeToTry.ToString()); - } - break; - } - - // Not found. Remove the name so we can try again. - scopeToTry.Length = dotpos; - } - } - } - - if (result == null) { - throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined."); - } else { - return result; - } - } - - /// <summary> - /// Struct used to hold the keys for the fieldByNumber table. - /// </summary> - struct DescriptorIntPair : IEquatable<DescriptorIntPair> { - - private readonly int number; - private readonly IDescriptor descriptor; - - internal DescriptorIntPair(IDescriptor descriptor, int number) { - this.number = number; - this.descriptor = descriptor; - } - - public bool Equals(DescriptorIntPair other) { - return descriptor == other.descriptor - && number == other.number; - } - - public override bool Equals(object obj) { - if (obj is DescriptorIntPair) { - return Equals((DescriptorIntPair)obj); - } - return false; - } - - public override int GetHashCode() { - return descriptor.GetHashCode() * ((1 << 16) - 1) + number; - } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System.Collections.Generic;
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Contains lookup tables containing all the descriptors defined in a particular file.
+ /// </summary>
+ internal sealed class DescriptorPool
+ {
+ private readonly IDictionary<string, IDescriptor> descriptorsByName =
+ new Dictionary<string, IDescriptor>();
+
+ private readonly IDictionary<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
+ new Dictionary<DescriptorIntPair, FieldDescriptor>();
+
+ private readonly IDictionary<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
+ new Dictionary<DescriptorIntPair, EnumValueDescriptor>();
+
+ private readonly DescriptorPool[] dependencies;
+
+ internal DescriptorPool(FileDescriptor[] dependencyFiles)
+ {
+ dependencies = new DescriptorPool[dependencyFiles.Length];
+ for (int i = 0; i < dependencyFiles.Length; i++)
+ {
+ dependencies[i] = dependencyFiles[i].DescriptorPool;
+ }
+
+ foreach (FileDescriptor dependency in dependencyFiles)
+ {
+ AddPackage(dependency.Package, dependency);
+ }
+ }
+
+ /// <summary>
+ /// Finds a symbol of the given name within the pool.
+ /// </summary>
+ /// <typeparam name="T">The type of symbol to look for</typeparam>
+ /// <param name="fullName">Fully-qualified name to look up</param>
+ /// <returns>The symbol with the given name and type,
+ /// or null if the symbol doesn't exist or has the wrong type</returns>
+ internal T FindSymbol<T>(string fullName) where T : class, IDescriptor
+ {
+ IDescriptor result;
+ descriptorsByName.TryGetValue(fullName, out result);
+ T descriptor = result as T;
+ if (descriptor != null)
+ {
+ return descriptor;
+ }
+
+ foreach (DescriptorPool dependency in dependencies)
+ {
+ dependency.descriptorsByName.TryGetValue(fullName, out result);
+ descriptor = result as T;
+ if (descriptor != null)
+ {
+ return descriptor;
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Adds a package to the symbol tables. If a package by the same name
+ /// already exists, that is fine, but if some other kind of symbol
+ /// exists under the same name, an exception is thrown. If the package
+ /// has multiple components, this also adds the parent package(s).
+ /// </summary>
+ internal void AddPackage(string fullName, FileDescriptor file)
+ {
+ int dotpos = fullName.LastIndexOf('.');
+ String name;
+ if (dotpos != -1)
+ {
+ AddPackage(fullName.Substring(0, dotpos), file);
+ name = fullName.Substring(dotpos + 1);
+ }
+ else
+ {
+ name = fullName;
+ }
+
+ IDescriptor old;
+ if (descriptorsByName.TryGetValue(fullName, out old))
+ {
+ if (!(old is PackageDescriptor))
+ {
+ throw new DescriptorValidationException(file,
+ "\"" + name +
+ "\" is already defined (as something other than a " +
+ "package) in file \"" + old.File.Name + "\".");
+ }
+ }
+ descriptorsByName[fullName] = new PackageDescriptor(name, fullName, file);
+ }
+
+ /// <summary>
+ /// Adds a symbol to the symbol table.
+ /// </summary>
+ /// <exception cref="DescriptorValidationException">The symbol already existed
+ /// in the symbol table.</exception>
+ internal void AddSymbol(IDescriptor descriptor)
+ {
+ ValidateSymbolName(descriptor);
+ String fullName = descriptor.FullName;
+
+ IDescriptor old;
+ if (descriptorsByName.TryGetValue(fullName, out old))
+ {
+ int dotPos = fullName.LastIndexOf('.');
+ string message;
+ if (descriptor.File == old.File)
+ {
+ if (dotPos == -1)
+ {
+ message = "\"" + fullName + "\" is already defined.";
+ }
+ else
+ {
+ message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" +
+ fullName.Substring(0, dotPos) + "\".";
+ }
+ }
+ else
+ {
+ message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\".";
+ }
+ throw new DescriptorValidationException(descriptor, message);
+ }
+ descriptorsByName[fullName] = descriptor;
+ }
+
+ private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$",
+ SilverlightCompatibility.CompiledRegexWhereAvailable);
+
+ /// <summary>
+ /// Verifies that the descriptor's name is valid (i.e. it contains
+ /// only letters, digits and underscores, and does not start with a digit).
+ /// </summary>
+ /// <param name="descriptor"></param>
+ private static void ValidateSymbolName(IDescriptor descriptor)
+ {
+ if (descriptor.Name == "")
+ {
+ throw new DescriptorValidationException(descriptor, "Missing name.");
+ }
+ if (!ValidationRegex.IsMatch(descriptor.Name))
+ {
+ throw new DescriptorValidationException(descriptor,
+ "\"" + descriptor.Name + "\" is not a valid identifier.");
+ }
+ }
+
+ /// <summary>
+ /// Returns the field with the given number in the given descriptor,
+ /// or null if it can't be found.
+ /// </summary>
+ internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number)
+ {
+ FieldDescriptor ret;
+ fieldsByNumber.TryGetValue(new DescriptorIntPair(messageDescriptor, number), out ret);
+ return ret;
+ }
+
+ internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number)
+ {
+ EnumValueDescriptor ret;
+ enumValuesByNumber.TryGetValue(new DescriptorIntPair(enumDescriptor, number), out ret);
+ return ret;
+ }
+
+ /// <summary>
+ /// Adds a field to the fieldsByNumber table.
+ /// </summary>
+ /// <exception cref="DescriptorValidationException">A field with the same
+ /// containing type and number already exists.</exception>
+ internal void AddFieldByNumber(FieldDescriptor field)
+ {
+ DescriptorIntPair key = new DescriptorIntPair(field.ContainingType, field.FieldNumber);
+ FieldDescriptor old;
+ if (fieldsByNumber.TryGetValue(key, out old))
+ {
+ throw new DescriptorValidationException(field, "Field number " + field.FieldNumber +
+ "has already been used in \"" +
+ field.ContainingType.FullName +
+ "\" by field \"" + old.Name + "\".");
+ }
+ fieldsByNumber[key] = field;
+ }
+
+ /// <summary>
+ /// Adds an enum value to the enumValuesByNumber table. If an enum value
+ /// with the same type and number already exists, this method does nothing.
+ /// (This is allowed; the first value defined with the number takes precedence.)
+ /// </summary>
+ internal void AddEnumValueByNumber(EnumValueDescriptor enumValue)
+ {
+ DescriptorIntPair key = new DescriptorIntPair(enumValue.EnumDescriptor, enumValue.Number);
+ if (!enumValuesByNumber.ContainsKey(key))
+ {
+ enumValuesByNumber[key] = enumValue;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a descriptor by name, relative to some other descriptor.
+ /// The name may be fully-qualified (with a leading '.'), partially-qualified,
+ /// or unqualified. C++-like name lookup semantics are used to search for the
+ /// matching descriptor.
+ /// </summary>
+ public IDescriptor LookupSymbol(string name, IDescriptor relativeTo)
+ {
+ // TODO(jonskeet): This could be optimized in a number of ways.
+
+ IDescriptor result;
+ if (name.StartsWith("."))
+ {
+ // Fully-qualified name.
+ result = FindSymbol<IDescriptor>(name.Substring(1));
+ }
+ else
+ {
+ // If "name" is a compound identifier, we want to search for the
+ // first component of it, then search within it for the rest.
+ int firstPartLength = name.IndexOf('.');
+ string firstPart = firstPartLength == -1 ? name : name.Substring(0, firstPartLength);
+
+ // We will search each parent scope of "relativeTo" looking for the
+ // symbol.
+ StringBuilder scopeToTry = new StringBuilder(relativeTo.FullName);
+
+ while (true)
+ {
+ // Chop off the last component of the scope.
+
+ // TODO(jonskeet): Make this more efficient. May not be worth using StringBuilder at all
+ int dotpos = scopeToTry.ToString().LastIndexOf(".");
+ if (dotpos == -1)
+ {
+ result = FindSymbol<IDescriptor>(name);
+ break;
+ }
+ else
+ {
+ scopeToTry.Length = dotpos + 1;
+
+ // Append firstPart and try to find.
+ scopeToTry.Append(firstPart);
+ result = FindSymbol<IDescriptor>(scopeToTry.ToString());
+
+ if (result != null)
+ {
+ if (firstPartLength != -1)
+ {
+ // We only found the first part of the symbol. Now look for
+ // the whole thing. If this fails, we *don't* want to keep
+ // searching parent scopes.
+ scopeToTry.Length = dotpos + 1;
+ scopeToTry.Append(name);
+ result = FindSymbol<IDescriptor>(scopeToTry.ToString());
+ }
+ break;
+ }
+
+ // Not found. Remove the name so we can try again.
+ scopeToTry.Length = dotpos;
+ }
+ }
+ }
+
+ if (result == null)
+ {
+ throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined.");
+ }
+ else
+ {
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Struct used to hold the keys for the fieldByNumber table.
+ /// </summary>
+ private struct DescriptorIntPair : IEquatable<DescriptorIntPair>
+ {
+ private readonly int number;
+ private readonly IDescriptor descriptor;
+
+ internal DescriptorIntPair(IDescriptor descriptor, int number)
+ {
+ this.number = number;
+ this.descriptor = descriptor;
+ }
+
+ public bool Equals(DescriptorIntPair other)
+ {
+ return descriptor == other.descriptor
+ && number == other.number;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is DescriptorIntPair)
+ {
+ return Equals((DescriptorIntPair) obj);
+ }
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return descriptor.GetHashCode()*((1 << 16) - 1) + number;
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs b/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs index 4d78b300..00efdbe8 100644 --- a/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs +++ b/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs @@ -1,59 +1,64 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System.Collections.Generic; -using Google.ProtocolBuffers.Collections; - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Internal class containing utility methods when working with descriptors. - /// </summary> - internal static class DescriptorUtil { - /// <summary> - /// Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert - /// arrays. - /// </summary> - internal delegate TOutput IndexedConverter<TInput, TOutput>(TInput element, int index); - - /// <summary> - /// Converts the given array into a read-only list, applying the specified conversion to - /// each input element. - /// </summary> - internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>(IList<TInput> input, - IndexedConverter<TInput, TOutput> converter) { - TOutput[] array = new TOutput[input.Count]; - for (int i = 0; i < array.Length; i++) { - array[i] = converter(input[i], i); - } - return Lists<TOutput>.AsReadOnly(array); - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Internal class containing utility methods when working with descriptors.
+ /// </summary>
+ internal static class DescriptorUtil
+ {
+ /// <summary>
+ /// Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert
+ /// arrays.
+ /// </summary>
+ internal delegate TOutput IndexedConverter<TInput, TOutput>(TInput element, int index);
+
+ /// <summary>
+ /// Converts the given array into a read-only list, applying the specified conversion to
+ /// each input element.
+ /// </summary>
+ internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>(IList<TInput> input,
+ IndexedConverter<TInput, TOutput>
+ converter)
+ {
+ TOutput[] array = new TOutput[input.Count];
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i] = converter(input[i], i);
+ }
+ return Lists<TOutput>.AsReadOnly(array);
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs b/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs index a262d173..d05d60d7 100644 --- a/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs +++ b/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs @@ -1,86 +1,90 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System; - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Thrown when building descriptors fails because the source DescriptorProtos - /// are not valid. - /// </summary> - public sealed class DescriptorValidationException : Exception { - - private readonly String name; - private readonly IMessage proto; - private readonly string description; - - /// <value> - /// The full name of the descriptor where the error occurred. - /// </value> - public String ProblemSymbolName { - get { return name; } - } - - /// <value> - /// The protocol message representation of the invalid descriptor. - /// </value> - public IMessage ProblemProto { - get { return proto; } - } - - /// <value> - /// A human-readable description of the error. (The Message property - /// is made up of the descriptor's name and this description.) - /// </value> - public string Description { - get { return description; } - } - - internal DescriptorValidationException(IDescriptor problemDescriptor, string description) : - base(problemDescriptor.FullName + ": " + description) { - - // Note that problemDescriptor may be partially uninitialized, so we - // don't want to expose it directly to the user. So, we only provide - // the name and the original proto. - name = problemDescriptor.FullName; - proto = problemDescriptor.Proto; - this.description = description; - } - - internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) : - base(problemDescriptor.FullName + ": " + description, cause) { - - name = problemDescriptor.FullName; - proto = problemDescriptor.Proto; - this.description = description; - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Thrown when building descriptors fails because the source DescriptorProtos
+ /// are not valid.
+ /// </summary>
+ public sealed class DescriptorValidationException : Exception
+ {
+ private readonly String name;
+ private readonly IMessage proto;
+ private readonly string description;
+
+ /// <value>
+ /// The full name of the descriptor where the error occurred.
+ /// </value>
+ public String ProblemSymbolName
+ {
+ get { return name; }
+ }
+
+ /// <value>
+ /// The protocol message representation of the invalid descriptor.
+ /// </value>
+ public IMessage ProblemProto
+ {
+ get { return proto; }
+ }
+
+ /// <value>
+ /// A human-readable description of the error. (The Message property
+ /// is made up of the descriptor's name and this description.)
+ /// </value>
+ public string Description
+ {
+ get { return description; }
+ }
+
+ internal DescriptorValidationException(IDescriptor problemDescriptor, string description) :
+ base(problemDescriptor.FullName + ": " + description)
+ {
+ // Note that problemDescriptor may be partially uninitialized, so we
+ // don't want to expose it directly to the user. So, we only provide
+ // the name and the original proto.
+ name = problemDescriptor.FullName;
+ proto = problemDescriptor.Proto;
+ this.description = description;
+ }
+
+ internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) :
+ base(problemDescriptor.FullName + ": " + description, cause)
+ {
+ name = problemDescriptor.FullName;
+ proto = problemDescriptor.Proto;
+ this.description = description;
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs index acf113de..80c2bd0f 100644 --- a/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs @@ -1,109 +1,121 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System.Collections.Generic; -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - - /// <summary> - /// Descriptor for an enum type in a .proto file. - /// </summary> - public sealed class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions>, IEnumLiteMap<EnumValueDescriptor> { - - private readonly MessageDescriptor containingType; - private readonly IList<EnumValueDescriptor> values; - - internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index) - : base(proto, file, ComputeFullName(file, parent, proto.Name), index) { - containingType = parent; - - if (proto.ValueCount == 0) { - // We cannot allow enums with no values because this would mean there - // would be no valid default value for fields of this type. - throw new DescriptorValidationException(this, "Enums must contain at least one value."); - } - - values = DescriptorUtil.ConvertAndMakeReadOnly(proto.ValueList, - (value, i) => new EnumValueDescriptor(value, file, this, i)); - - File.DescriptorPool.AddSymbol(this); - } - - /// <value> - /// If this is a nested type, get the outer descriptor, otherwise null. - /// </value> - public MessageDescriptor ContainingType { - get { return containingType; } - } - - /// <value> - /// An unmodifiable list of defined value descriptors for this enum. - /// </value> - public IList<EnumValueDescriptor> Values { - get { return values; } - } - - /// <summary> - /// Logic moved from FieldSet to continue current behavior - /// </summary> - public bool IsValidValue(IEnumLite value) { - return value is EnumValueDescriptor && ((EnumValueDescriptor)value).EnumDescriptor == this; - } - - /// <summary> - /// Finds an enum value by number. If multiple enum values have the - /// same number, this returns the first defined value with that number. - /// </summary> - public EnumValueDescriptor FindValueByNumber(int number) { - return File.DescriptorPool.FindEnumValueByNumber(this, number); - } - - IEnumLite IEnumLiteMap.FindValueByNumber(int number) { - return FindValueByNumber(number); - } - /// <summary> - /// Finds an enum value by name. - /// </summary> - /// <param name="name">The unqualified name of the value (e.g. "FOO").</param> - /// <returns>The value's descriptor, or null if not found.</returns> - public EnumValueDescriptor FindValueByName(string name) { - return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name); - } - - internal override void ReplaceProto(EnumDescriptorProto newProto) { - base.ReplaceProto(newProto); - for (int i = 0; i < values.Count; i++) { - values[i].ReplaceProto(newProto.GetValue(i)); - } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System.Collections.Generic;
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Descriptor for an enum type in a .proto file.
+ /// </summary>
+ public sealed class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions>,
+ IEnumLiteMap<EnumValueDescriptor>
+ {
+ private readonly MessageDescriptor containingType;
+ private readonly IList<EnumValueDescriptor> values;
+
+ internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)
+ : base(proto, file, ComputeFullName(file, parent, proto.Name), index)
+ {
+ containingType = parent;
+
+ if (proto.ValueCount == 0)
+ {
+ // We cannot allow enums with no values because this would mean there
+ // would be no valid default value for fields of this type.
+ throw new DescriptorValidationException(this, "Enums must contain at least one value.");
+ }
+
+ values = DescriptorUtil.ConvertAndMakeReadOnly(proto.ValueList,
+ (value, i) => new EnumValueDescriptor(value, file, this, i));
+
+ File.DescriptorPool.AddSymbol(this);
+ }
+
+ /// <value>
+ /// If this is a nested type, get the outer descriptor, otherwise null.
+ /// </value>
+ public MessageDescriptor ContainingType
+ {
+ get { return containingType; }
+ }
+
+ /// <value>
+ /// An unmodifiable list of defined value descriptors for this enum.
+ /// </value>
+ public IList<EnumValueDescriptor> Values
+ {
+ get { return values; }
+ }
+
+ /// <summary>
+ /// Logic moved from FieldSet to continue current behavior
+ /// </summary>
+ public bool IsValidValue(IEnumLite value)
+ {
+ return value is EnumValueDescriptor && ((EnumValueDescriptor) value).EnumDescriptor == this;
+ }
+
+ /// <summary>
+ /// Finds an enum value by number. If multiple enum values have the
+ /// same number, this returns the first defined value with that number.
+ /// </summary>
+ public EnumValueDescriptor FindValueByNumber(int number)
+ {
+ return File.DescriptorPool.FindEnumValueByNumber(this, number);
+ }
+
+ IEnumLite IEnumLiteMap.FindValueByNumber(int number)
+ {
+ return FindValueByNumber(number);
+ }
+
+ /// <summary>
+ /// Finds an enum value by name.
+ /// </summary>
+ /// <param name="name">The unqualified name of the value (e.g. "FOO").</param>
+ /// <returns>The value's descriptor, or null if not found.</returns>
+ public EnumValueDescriptor FindValueByName(string name)
+ {
+ return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name);
+ }
+
+ internal override void ReplaceProto(EnumDescriptorProto newProto)
+ {
+ base.ReplaceProto(newProto);
+ for (int i = 0; i < values.Count; i++)
+ {
+ values[i].ReplaceProto(newProto.GetValue(i));
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs b/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs index 732dec06..afb9cbbc 100644 --- a/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs @@ -1,59 +1,63 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - - /// <summary> - /// Descriptor for a single enum value within an enum in a .proto file. - /// </summary> - public sealed class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions>, IEnumLite { - - private readonly EnumDescriptor enumDescriptor; - - internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file, - EnumDescriptor parent, int index) - : base (proto, file, parent.FullName + "." + proto.Name, index) { - enumDescriptor = parent; - file.DescriptorPool.AddSymbol(this); - file.DescriptorPool.AddEnumValueByNumber(this); - } - - public int Number { - get { return Proto.Number; } - } - - public EnumDescriptor EnumDescriptor { - get { return enumDescriptor; } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Descriptor for a single enum value within an enum in a .proto file.
+ /// </summary>
+ public sealed class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions>,
+ IEnumLite
+ {
+ private readonly EnumDescriptor enumDescriptor;
+
+ internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file,
+ EnumDescriptor parent, int index)
+ : base(proto, file, parent.FullName + "." + proto.Name, index)
+ {
+ enumDescriptor = parent;
+ file.DescriptorPool.AddSymbol(this);
+ file.DescriptorPool.AddEnumValueByNumber(this);
+ }
+
+ public int Number
+ {
+ get { return Proto.Number; }
+ }
+
+ public EnumDescriptor EnumDescriptor
+ {
+ get { return enumDescriptor; }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs b/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs index 854b3a89..8653a078 100644 --- a/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs @@ -1,521 +1,666 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System; -using System.Collections.Generic; -using System.Reflection; -using Google.ProtocolBuffers.Collections; -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - - /// <summary> - /// Descriptor for a field or extension within a message in a .proto file. - /// </summary> - public sealed class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>, IComparable<FieldDescriptor>, IFieldDescriptorLite { - - private readonly MessageDescriptor extensionScope; - private EnumDescriptor enumType; - private MessageDescriptor messageType; - private MessageDescriptor containingType; - private object defaultValue; - private FieldType fieldType; - private MappedType mappedType; - - private CSharpFieldOptions csharpFieldOptions; - private readonly object optionsLock = new object(); - - internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, - MessageDescriptor parent, int index, bool isExtension) - : base(proto, file, ComputeFullName(file, parent, proto.Name), index) { - - if (proto.HasType) { - fieldType = GetFieldTypeFromProtoType(proto.Type); - mappedType = FieldTypeToMappedTypeMap[fieldType]; - } - - if (FieldNumber <= 0) { - throw new DescriptorValidationException(this, - "Field numbers must be positive integers."); - } - - if (isExtension) { - if (!proto.HasExtendee) { - throw new DescriptorValidationException(this, - "FieldDescriptorProto.Extendee not set for extension field."); - } - containingType = null; // Will be filled in when cross-linking - if (parent != null) { - extensionScope = parent; - } else { - extensionScope = null; - } - } else { - if (proto.HasExtendee) { - throw new DescriptorValidationException(this, - "FieldDescriptorProto.Extendee set for non-extension field."); - } - containingType = parent; - extensionScope = null; - } - - file.DescriptorPool.AddSymbol(this); - } - - private CSharpFieldOptions BuildOrFakeCSharpOptions() { - // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues - if (File.Proto.Name == "google/protobuf/csharp_options.proto") { - if (Name=="csharp_field_options") { - return new CSharpFieldOptions.Builder { PropertyName = "CSharpFieldOptions" }.Build(); - } - if (Name=="csharp_file_options") { - return new CSharpFieldOptions.Builder { PropertyName = "CSharpFileOptions" }.Build(); - } - } - CSharpFieldOptions.Builder builder = CSharpFieldOptions.CreateBuilder(); - if (Proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFieldOptions)) { - builder.MergeFrom(Proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFieldOptions)); - } - if (!builder.HasPropertyName) { - string fieldName = FieldType == FieldType.Group ? MessageType.Name : Name; - string propertyName = NameHelpers.UnderscoresToPascalCase(fieldName); - if (propertyName == ContainingType.Name) { - propertyName += "_"; - } - builder.PropertyName = propertyName; - } - return builder.Build(); - } - - /// <summary> - /// Maps a field type as included in the .proto file to a FieldType. - /// </summary> - private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type) { - switch (type) { - case FieldDescriptorProto.Types.Type.TYPE_DOUBLE: return FieldType.Double; - case FieldDescriptorProto.Types.Type.TYPE_FLOAT: return FieldType.Float; - case FieldDescriptorProto.Types.Type.TYPE_INT64: return FieldType.Int64; - case FieldDescriptorProto.Types.Type.TYPE_UINT64: return FieldType.UInt64; - case FieldDescriptorProto.Types.Type.TYPE_INT32: return FieldType.Int32; - case FieldDescriptorProto.Types.Type.TYPE_FIXED64: return FieldType.Fixed64; - case FieldDescriptorProto.Types.Type.TYPE_FIXED32: return FieldType.Fixed32; - case FieldDescriptorProto.Types.Type.TYPE_BOOL: return FieldType.Bool; - case FieldDescriptorProto.Types.Type.TYPE_STRING: return FieldType.String; - case FieldDescriptorProto.Types.Type.TYPE_GROUP: return FieldType.Group; - case FieldDescriptorProto.Types.Type.TYPE_MESSAGE: return FieldType.Message; - case FieldDescriptorProto.Types.Type.TYPE_BYTES: return FieldType.Bytes; - case FieldDescriptorProto.Types.Type.TYPE_UINT32: return FieldType.UInt32; - case FieldDescriptorProto.Types.Type.TYPE_ENUM: return FieldType.Enum; - case FieldDescriptorProto.Types.Type.TYPE_SFIXED32: return FieldType.SFixed32; - case FieldDescriptorProto.Types.Type.TYPE_SFIXED64: return FieldType.SFixed64; - case FieldDescriptorProto.Types.Type.TYPE_SINT32: return FieldType.SInt32; - case FieldDescriptorProto.Types.Type.TYPE_SINT64: return FieldType.SInt64; - default: - throw new ArgumentException("Invalid type specified"); - } - } - - /// <summary> - /// Returns the default value for a mapped type. - /// </summary> - private static object GetDefaultValueForMappedType(MappedType type) { - switch (type) { - case MappedType.Int32: return 0; - case MappedType.Int64: return (long) 0; - case MappedType.UInt32: return (uint) 0; - case MappedType.UInt64: return (ulong) 0; - case MappedType.Single: return (float) 0; - case MappedType.Double: return (double) 0; - case MappedType.Boolean: return false; - case MappedType.String: return ""; - case MappedType.ByteString: return ByteString.Empty; - case MappedType.Message: return null; - case MappedType.Enum: return null; - default: - throw new ArgumentException("Invalid type specified"); - } - } - - public bool IsRequired { - get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REQUIRED; } - } - - public bool IsOptional { - get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; } - } - - public bool IsRepeated { - get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; } - } - - public bool IsPacked { - get { return Proto.Options.Packed; } - } - - /// <valule> - /// Indicates whether or not the field had an explicitly-defined default value. - /// </value> - public bool HasDefaultValue { - get { return Proto.HasDefaultValue; } - } - - /// <value> - /// The field's default value. Valid for all types except messages - /// and groups. For all other types, the object returned is of the - /// same class that would be returned by IMessage[this]. - /// For repeated fields this will always be an empty immutable list compatible with IList[object]. - /// For message fields it will always be null. For singular values, it will depend on the descriptor. - /// </value> - public object DefaultValue { - get { - if (MappedType == MappedType.Message) { - throw new InvalidOperationException("FieldDescriptor.DefaultValue called on an embedded message field."); - } - return defaultValue; - } - } - - /// <value> - /// Indicates whether or not this field is an extension. - /// </value> - public bool IsExtension { - get { return Proto.HasExtendee; } - } - - /* - * Get the field's containing type. For extensions, this is the type being - * extended, not the location where the extension was defined. See - * {@link #getExtensionScope()}. - */ - /// <summary> - /// Get the field's containing type. For extensions, this is the type being - /// extended, not the location where the extension was defined. See - /// <see cref="ExtensionScope" />. - /// </summary> - public MessageDescriptor ContainingType { - get { return containingType; } - } - - /// <summary> - /// Returns the C#-specific options for this field descriptor. This will always be - /// completely filled in. - /// </summary> - public CSharpFieldOptions CSharpOptions { - get { - lock (optionsLock) { - if (csharpFieldOptions == null) { - csharpFieldOptions = BuildOrFakeCSharpOptions(); - } - } - return csharpFieldOptions; - } - } - - /// <summary> - /// For extensions defined nested within message types, gets - /// the outer type. Not valid for non-extension fields. - /// </summary> - /// <example> - /// <code> - /// message Foo { - /// extensions 1000 to max; - /// } - /// extend Foo { - /// optional int32 baz = 1234; - /// } - /// message Bar { - /// extend Foo { - /// optional int32 qux = 4321; - /// } - /// } - /// </code> - /// The containing type for both <c>baz</c> and <c>qux</c> is <c>Foo</c>. - /// However, the extension scope for <c>baz</c> is <c>null</c> while - /// the extension scope for <c>qux</c> is <c>Bar</c>. - /// </example> - public MessageDescriptor ExtensionScope { - get { - if (!IsExtension) { - throw new InvalidOperationException("This field is not an extension."); - } - return extensionScope; - } - } - - public MappedType MappedType { - get { return mappedType; } - } - - public FieldType FieldType { - get { return fieldType; } - } - - public bool IsCLSCompliant { - get { return mappedType != MappedType.UInt32 && mappedType != MappedType.UInt64; } - } - - public int FieldNumber { - get { return Proto.Number; } - } - - /// <summary> - /// Compares this descriptor with another one, ordering in "canonical" order - /// which simply means ascending order by field number. <paramref name="other"/> - /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of - /// both fields must be the same. - /// </summary> - public int CompareTo(FieldDescriptor other) { - if (other.containingType != containingType) { - throw new ArgumentException("FieldDescriptors can only be compared to other FieldDescriptors " + - "for fields of the same message type."); - } - return FieldNumber - other.FieldNumber; - } - - /// <summary> - /// Compares this descriptor with another one, ordering in "canonical" order - /// which simply means ascending order by field number. <paramref name="other"/> - /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of - /// both fields must be the same. - /// </summary> - public int CompareTo(IFieldDescriptorLite other) { - return FieldNumber - other.FieldNumber; - } - - IEnumLiteMap IFieldDescriptorLite.EnumType { - get { return EnumType; } - } - - bool IFieldDescriptorLite.MessageSetWireFormat { - get { return ContainingType.Options.MessageSetWireFormat; } - } - - /// <summary> - /// For enum fields, returns the field's type. - /// </summary> - public EnumDescriptor EnumType { - get { - if (MappedType != MappedType.Enum) { - throw new InvalidOperationException("EnumType is only valid for enum fields."); - } - return enumType; - } - } - - /// <summary> - /// For embedded message and group fields, returns the field's type. - /// </summary> - public MessageDescriptor MessageType { - get { - if (MappedType != MappedType.Message) { - throw new InvalidOperationException("MessageType is only valid for enum fields."); - } - return messageType; - } - } - - /// <summary> - /// Immutable mapping from field type to mapped type. Built using the attributes on - /// FieldType values. - /// </summary> - public static readonly IDictionary<FieldType, MappedType> FieldTypeToMappedTypeMap = MapFieldTypes(); - - private static IDictionary<FieldType, MappedType> MapFieldTypes() { - var map = new Dictionary<FieldType, MappedType>(); - foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) { - FieldType fieldType = (FieldType)field.GetValue(null); - FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0]; - map[fieldType] = mapping.MappedType; - } - return Dictionaries.AsReadOnly(map); - } - - /// <summary> - /// Look up and cross-link all field types etc. - /// </summary> - internal void CrossLink() { - if (Proto.HasExtendee) { - IDescriptor extendee = File.DescriptorPool.LookupSymbol(Proto.Extendee, this); - if (!(extendee is MessageDescriptor)) { - throw new DescriptorValidationException(this, "\"" + Proto.Extendee + "\" is not a message type."); - } - containingType = (MessageDescriptor) extendee; - - if (!containingType.IsExtensionNumber(FieldNumber)) { - throw new DescriptorValidationException(this, - "\"" + containingType.FullName + "\" does not declare " + FieldNumber + " as an extension number."); - } - } - - if (Proto.HasTypeName) { - IDescriptor typeDescriptor = - File.DescriptorPool.LookupSymbol(Proto.TypeName, this); - - if (!Proto.HasType) { - // Choose field type based on symbol. - if (typeDescriptor is MessageDescriptor) { - fieldType = FieldType.Message; - mappedType = MappedType.Message; - } else if (typeDescriptor is EnumDescriptor) { - fieldType = FieldType.Enum; - mappedType = MappedType.Enum; - } else { - throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a type."); - } - } - - if (MappedType == MappedType.Message) { - if (!(typeDescriptor is MessageDescriptor)) { - throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a message type."); - } - messageType = (MessageDescriptor) typeDescriptor; - - if (Proto.HasDefaultValue) { - throw new DescriptorValidationException(this, "Messages can't have default values."); - } - } else if (MappedType == Descriptors.MappedType.Enum) { - if (!(typeDescriptor is EnumDescriptor)) { - throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not an enum type."); - } - enumType = (EnumDescriptor)typeDescriptor; - } else { - throw new DescriptorValidationException(this, "Field with primitive type has type_name."); - } - } else { - if (MappedType == MappedType.Message || MappedType == MappedType.Enum) { - throw new DescriptorValidationException(this, "Field with message or enum type missing type_name."); - } - } - - // We don't attempt to parse the default value until here because for - // enums we need the enum type's descriptor. - if (Proto.HasDefaultValue) { - if (IsRepeated) { - throw new DescriptorValidationException(this, "Repeated fields cannot have default values."); - } - - try { - switch (FieldType) { - case FieldType.Int32: - case FieldType.SInt32: - case FieldType.SFixed32: - defaultValue = TextFormat.ParseInt32(Proto.DefaultValue); - break; - case FieldType.UInt32: - case FieldType.Fixed32: - defaultValue = TextFormat.ParseUInt32(Proto.DefaultValue); - break; - case FieldType.Int64: - case FieldType.SInt64: - case FieldType.SFixed64: - defaultValue = TextFormat.ParseInt64(Proto.DefaultValue); - break; - case FieldType.UInt64: - case FieldType.Fixed64: - defaultValue = TextFormat.ParseUInt64(Proto.DefaultValue); - break; - case FieldType.Float: - defaultValue = TextFormat.ParseFloat(Proto.DefaultValue); - break; - case FieldType.Double: - defaultValue = TextFormat.ParseDouble(Proto.DefaultValue); - break; - case FieldType.Bool: - if (Proto.DefaultValue == "true") { - defaultValue = true; - } else if (Proto.DefaultValue == "false") { - defaultValue = false; - } else { - throw new FormatException("Boolean values must be \"true\" or \"false\""); - } - break; - case FieldType.String: - defaultValue = Proto.DefaultValue; - break; - case FieldType.Bytes: - try { - defaultValue = TextFormat.UnescapeBytes(Proto.DefaultValue); - } catch (FormatException e) { - throw new DescriptorValidationException(this, "Couldn't parse default value: " + e.Message); - } - break; - case FieldType.Enum: - defaultValue = enumType.FindValueByName(Proto.DefaultValue); - if (defaultValue == null) { - throw new DescriptorValidationException(this, "Unknown enum default value: \"" + Proto.DefaultValue + "\""); - } - break; - case FieldType.Message: - case FieldType.Group: - throw new DescriptorValidationException(this, "Message type had default value."); - } - } catch (FormatException e) { - DescriptorValidationException validationException = - new DescriptorValidationException(this, "Could not parse default value: \"" + Proto.DefaultValue + "\"", e); - throw validationException; - } - } else { - // Determine the default default for this field. - if (IsRepeated) { - defaultValue = Lists<object>.Empty; - } else { - switch (MappedType) { - case MappedType.Enum: - // We guarantee elsewhere that an enum type always has at least - // one possible value. - defaultValue = enumType.Values[0]; - break; - case MappedType.Message: - defaultValue = null; - break; - default: - defaultValue = GetDefaultValueForMappedType(MappedType); - break; - } - } - } - - if (!IsExtension) { - File.DescriptorPool.AddFieldByNumber(this); - } - - if (containingType != null && containingType.Options.MessageSetWireFormat) { - if (IsExtension) { - if (!IsOptional || FieldType != FieldType.Message) { - throw new DescriptorValidationException(this, "Extensions of MessageSets must be optional messages."); - } - } else { - throw new DescriptorValidationException(this, "MessageSets cannot have fields, only extensions."); - } - } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Google.ProtocolBuffers.Collections;
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Descriptor for a field or extension within a message in a .proto file.
+ /// </summary>
+ public sealed class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>,
+ IComparable<FieldDescriptor>, IFieldDescriptorLite
+ {
+ private readonly MessageDescriptor extensionScope;
+ private EnumDescriptor enumType;
+ private MessageDescriptor messageType;
+ private MessageDescriptor containingType;
+ private object defaultValue;
+ private FieldType fieldType;
+ private MappedType mappedType;
+
+ private CSharpFieldOptions csharpFieldOptions;
+ private readonly object optionsLock = new object();
+
+ internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
+ MessageDescriptor parent, int index, bool isExtension)
+ : base(proto, file, ComputeFullName(file, parent, proto.Name), index)
+ {
+ if (proto.HasType)
+ {
+ fieldType = GetFieldTypeFromProtoType(proto.Type);
+ mappedType = FieldTypeToMappedTypeMap[fieldType];
+ }
+
+ if (FieldNumber <= 0)
+ {
+ throw new DescriptorValidationException(this,
+ "Field numbers must be positive integers.");
+ }
+
+ if (isExtension)
+ {
+ if (!proto.HasExtendee)
+ {
+ throw new DescriptorValidationException(this,
+ "FieldDescriptorProto.Extendee not set for extension field.");
+ }
+ containingType = null; // Will be filled in when cross-linking
+ if (parent != null)
+ {
+ extensionScope = parent;
+ }
+ else
+ {
+ extensionScope = null;
+ }
+ }
+ else
+ {
+ if (proto.HasExtendee)
+ {
+ throw new DescriptorValidationException(this,
+ "FieldDescriptorProto.Extendee set for non-extension field.");
+ }
+ containingType = parent;
+ extensionScope = null;
+ }
+
+ file.DescriptorPool.AddSymbol(this);
+ }
+
+ private CSharpFieldOptions BuildOrFakeCSharpOptions()
+ {
+ // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues
+ if (File.Proto.Name == "google/protobuf/csharp_options.proto")
+ {
+ if (Name == "csharp_field_options")
+ {
+ return new CSharpFieldOptions.Builder {PropertyName = "CSharpFieldOptions"}.Build();
+ }
+ if (Name == "csharp_file_options")
+ {
+ return new CSharpFieldOptions.Builder {PropertyName = "CSharpFileOptions"}.Build();
+ }
+ }
+ CSharpFieldOptions.Builder builder = CSharpFieldOptions.CreateBuilder();
+ if (Proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFieldOptions))
+ {
+ builder.MergeFrom(Proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFieldOptions));
+ }
+ if (!builder.HasPropertyName)
+ {
+ string fieldName = FieldType == FieldType.Group ? MessageType.Name : Name;
+ string propertyName = NameHelpers.UnderscoresToPascalCase(fieldName);
+ if (propertyName == ContainingType.Name)
+ {
+ propertyName += "_";
+ }
+ builder.PropertyName = propertyName;
+ }
+ return builder.Build();
+ }
+
+ /// <summary>
+ /// Maps a field type as included in the .proto file to a FieldType.
+ /// </summary>
+ private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type)
+ {
+ switch (type)
+ {
+ case FieldDescriptorProto.Types.Type.TYPE_DOUBLE:
+ return FieldType.Double;
+ case FieldDescriptorProto.Types.Type.TYPE_FLOAT:
+ return FieldType.Float;
+ case FieldDescriptorProto.Types.Type.TYPE_INT64:
+ return FieldType.Int64;
+ case FieldDescriptorProto.Types.Type.TYPE_UINT64:
+ return FieldType.UInt64;
+ case FieldDescriptorProto.Types.Type.TYPE_INT32:
+ return FieldType.Int32;
+ case FieldDescriptorProto.Types.Type.TYPE_FIXED64:
+ return FieldType.Fixed64;
+ case FieldDescriptorProto.Types.Type.TYPE_FIXED32:
+ return FieldType.Fixed32;
+ case FieldDescriptorProto.Types.Type.TYPE_BOOL:
+ return FieldType.Bool;
+ case FieldDescriptorProto.Types.Type.TYPE_STRING:
+ return FieldType.String;
+ case FieldDescriptorProto.Types.Type.TYPE_GROUP:
+ return FieldType.Group;
+ case FieldDescriptorProto.Types.Type.TYPE_MESSAGE:
+ return FieldType.Message;
+ case FieldDescriptorProto.Types.Type.TYPE_BYTES:
+ return FieldType.Bytes;
+ case FieldDescriptorProto.Types.Type.TYPE_UINT32:
+ return FieldType.UInt32;
+ case FieldDescriptorProto.Types.Type.TYPE_ENUM:
+ return FieldType.Enum;
+ case FieldDescriptorProto.Types.Type.TYPE_SFIXED32:
+ return FieldType.SFixed32;
+ case FieldDescriptorProto.Types.Type.TYPE_SFIXED64:
+ return FieldType.SFixed64;
+ case FieldDescriptorProto.Types.Type.TYPE_SINT32:
+ return FieldType.SInt32;
+ case FieldDescriptorProto.Types.Type.TYPE_SINT64:
+ return FieldType.SInt64;
+ default:
+ throw new ArgumentException("Invalid type specified");
+ }
+ }
+
+ /// <summary>
+ /// Returns the default value for a mapped type.
+ /// </summary>
+ private static object GetDefaultValueForMappedType(MappedType type)
+ {
+ switch (type)
+ {
+ case MappedType.Int32:
+ return 0;
+ case MappedType.Int64:
+ return (long) 0;
+ case MappedType.UInt32:
+ return (uint) 0;
+ case MappedType.UInt64:
+ return (ulong) 0;
+ case MappedType.Single:
+ return (float) 0;
+ case MappedType.Double:
+ return (double) 0;
+ case MappedType.Boolean:
+ return false;
+ case MappedType.String:
+ return "";
+ case MappedType.ByteString:
+ return ByteString.Empty;
+ case MappedType.Message:
+ return null;
+ case MappedType.Enum:
+ return null;
+ default:
+ throw new ArgumentException("Invalid type specified");
+ }
+ }
+
+ public bool IsRequired
+ {
+ get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REQUIRED; }
+ }
+
+ public bool IsOptional
+ {
+ get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; }
+ }
+
+ public bool IsRepeated
+ {
+ get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; }
+ }
+
+ public bool IsPacked
+ {
+ get { return Proto.Options.Packed; }
+ }
+
+ /// <valule>
+ /// Indicates whether or not the field had an explicitly-defined default value.
+ /// </value>
+ public bool HasDefaultValue
+ {
+ get { return Proto.HasDefaultValue; }
+ }
+
+ /// <value>
+ /// The field's default value. Valid for all types except messages
+ /// and groups. For all other types, the object returned is of the
+ /// same class that would be returned by IMessage[this].
+ /// For repeated fields this will always be an empty immutable list compatible with IList[object].
+ /// For message fields it will always be null. For singular values, it will depend on the descriptor.
+ /// </value>
+ public object DefaultValue
+ {
+ get
+ {
+ if (MappedType == MappedType.Message)
+ {
+ throw new InvalidOperationException(
+ "FieldDescriptor.DefaultValue called on an embedded message field.");
+ }
+ return defaultValue;
+ }
+ }
+
+ /// <value>
+ /// Indicates whether or not this field is an extension.
+ /// </value>
+ public bool IsExtension
+ {
+ get { return Proto.HasExtendee; }
+ }
+
+ /*
+ * Get the field's containing type. For extensions, this is the type being
+ * extended, not the location where the extension was defined. See
+ * {@link #getExtensionScope()}.
+ */
+
+ /// <summary>
+ /// Get the field's containing type. For extensions, this is the type being
+ /// extended, not the location where the extension was defined. See
+ /// <see cref="ExtensionScope" />.
+ /// </summary>
+ public MessageDescriptor ContainingType
+ {
+ get { return containingType; }
+ }
+
+ /// <summary>
+ /// Returns the C#-specific options for this field descriptor. This will always be
+ /// completely filled in.
+ /// </summary>
+ public CSharpFieldOptions CSharpOptions
+ {
+ get
+ {
+ lock (optionsLock)
+ {
+ if (csharpFieldOptions == null)
+ {
+ csharpFieldOptions = BuildOrFakeCSharpOptions();
+ }
+ }
+ return csharpFieldOptions;
+ }
+ }
+
+ /// <summary>
+ /// For extensions defined nested within message types, gets
+ /// the outer type. Not valid for non-extension fields.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// message Foo {
+ /// extensions 1000 to max;
+ /// }
+ /// extend Foo {
+ /// optional int32 baz = 1234;
+ /// }
+ /// message Bar {
+ /// extend Foo {
+ /// optional int32 qux = 4321;
+ /// }
+ /// }
+ /// </code>
+ /// The containing type for both <c>baz</c> and <c>qux</c> is <c>Foo</c>.
+ /// However, the extension scope for <c>baz</c> is <c>null</c> while
+ /// the extension scope for <c>qux</c> is <c>Bar</c>.
+ /// </example>
+ public MessageDescriptor ExtensionScope
+ {
+ get
+ {
+ if (!IsExtension)
+ {
+ throw new InvalidOperationException("This field is not an extension.");
+ }
+ return extensionScope;
+ }
+ }
+
+ public MappedType MappedType
+ {
+ get { return mappedType; }
+ }
+
+ public FieldType FieldType
+ {
+ get { return fieldType; }
+ }
+
+ public bool IsCLSCompliant
+ {
+ get { return mappedType != MappedType.UInt32 && mappedType != MappedType.UInt64; }
+ }
+
+ public int FieldNumber
+ {
+ get { return Proto.Number; }
+ }
+
+ /// <summary>
+ /// Compares this descriptor with another one, ordering in "canonical" order
+ /// which simply means ascending order by field number. <paramref name="other"/>
+ /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of
+ /// both fields must be the same.
+ /// </summary>
+ public int CompareTo(FieldDescriptor other)
+ {
+ if (other.containingType != containingType)
+ {
+ throw new ArgumentException("FieldDescriptors can only be compared to other FieldDescriptors " +
+ "for fields of the same message type.");
+ }
+ return FieldNumber - other.FieldNumber;
+ }
+
+ /// <summary>
+ /// Compares this descriptor with another one, ordering in "canonical" order
+ /// which simply means ascending order by field number. <paramref name="other"/>
+ /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of
+ /// both fields must be the same.
+ /// </summary>
+ public int CompareTo(IFieldDescriptorLite other)
+ {
+ return FieldNumber - other.FieldNumber;
+ }
+
+ IEnumLiteMap IFieldDescriptorLite.EnumType
+ {
+ get { return EnumType; }
+ }
+
+ bool IFieldDescriptorLite.MessageSetWireFormat
+ {
+ get { return ContainingType.Options.MessageSetWireFormat; }
+ }
+
+ /// <summary>
+ /// For enum fields, returns the field's type.
+ /// </summary>
+ public EnumDescriptor EnumType
+ {
+ get
+ {
+ if (MappedType != MappedType.Enum)
+ {
+ throw new InvalidOperationException("EnumType is only valid for enum fields.");
+ }
+ return enumType;
+ }
+ }
+
+ /// <summary>
+ /// For embedded message and group fields, returns the field's type.
+ /// </summary>
+ public MessageDescriptor MessageType
+ {
+ get
+ {
+ if (MappedType != MappedType.Message)
+ {
+ throw new InvalidOperationException("MessageType is only valid for enum fields.");
+ }
+ return messageType;
+ }
+ }
+
+ /// <summary>
+ /// Immutable mapping from field type to mapped type. Built using the attributes on
+ /// FieldType values.
+ /// </summary>
+ public static readonly IDictionary<FieldType, MappedType> FieldTypeToMappedTypeMap = MapFieldTypes();
+
+ private static IDictionary<FieldType, MappedType> MapFieldTypes()
+ {
+ var map = new Dictionary<FieldType, MappedType>();
+ foreach (FieldInfo field in typeof (FieldType).GetFields(BindingFlags.Static | BindingFlags.Public))
+ {
+ FieldType fieldType = (FieldType) field.GetValue(null);
+ FieldMappingAttribute mapping =
+ (FieldMappingAttribute) field.GetCustomAttributes(typeof (FieldMappingAttribute), false)[0];
+ map[fieldType] = mapping.MappedType;
+ }
+ return Dictionaries.AsReadOnly(map);
+ }
+
+ /// <summary>
+ /// Look up and cross-link all field types etc.
+ /// </summary>
+ internal void CrossLink()
+ {
+ if (Proto.HasExtendee)
+ {
+ IDescriptor extendee = File.DescriptorPool.LookupSymbol(Proto.Extendee, this);
+ if (!(extendee is MessageDescriptor))
+ {
+ throw new DescriptorValidationException(this, "\"" + Proto.Extendee + "\" is not a message type.");
+ }
+ containingType = (MessageDescriptor) extendee;
+
+ if (!containingType.IsExtensionNumber(FieldNumber))
+ {
+ throw new DescriptorValidationException(this,
+ "\"" + containingType.FullName + "\" does not declare " +
+ FieldNumber + " as an extension number.");
+ }
+ }
+
+ if (Proto.HasTypeName)
+ {
+ IDescriptor typeDescriptor =
+ File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
+
+ if (!Proto.HasType)
+ {
+ // Choose field type based on symbol.
+ if (typeDescriptor is MessageDescriptor)
+ {
+ fieldType = FieldType.Message;
+ mappedType = MappedType.Message;
+ }
+ else if (typeDescriptor is EnumDescriptor)
+ {
+ fieldType = FieldType.Enum;
+ mappedType = MappedType.Enum;
+ }
+ else
+ {
+ throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a type.");
+ }
+ }
+
+ if (MappedType == MappedType.Message)
+ {
+ if (!(typeDescriptor is MessageDescriptor))
+ {
+ throw new DescriptorValidationException(this,
+ "\"" + Proto.TypeName + "\" is not a message type.");
+ }
+ messageType = (MessageDescriptor) typeDescriptor;
+
+ if (Proto.HasDefaultValue)
+ {
+ throw new DescriptorValidationException(this, "Messages can't have default values.");
+ }
+ }
+ else if (MappedType == Descriptors.MappedType.Enum)
+ {
+ if (!(typeDescriptor is EnumDescriptor))
+ {
+ throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not an enum type.");
+ }
+ enumType = (EnumDescriptor) typeDescriptor;
+ }
+ else
+ {
+ throw new DescriptorValidationException(this, "Field with primitive type has type_name.");
+ }
+ }
+ else
+ {
+ if (MappedType == MappedType.Message || MappedType == MappedType.Enum)
+ {
+ throw new DescriptorValidationException(this, "Field with message or enum type missing type_name.");
+ }
+ }
+
+ // We don't attempt to parse the default value until here because for
+ // enums we need the enum type's descriptor.
+ if (Proto.HasDefaultValue)
+ {
+ if (IsRepeated)
+ {
+ throw new DescriptorValidationException(this, "Repeated fields cannot have default values.");
+ }
+
+ try
+ {
+ switch (FieldType)
+ {
+ case FieldType.Int32:
+ case FieldType.SInt32:
+ case FieldType.SFixed32:
+ defaultValue = TextFormat.ParseInt32(Proto.DefaultValue);
+ break;
+ case FieldType.UInt32:
+ case FieldType.Fixed32:
+ defaultValue = TextFormat.ParseUInt32(Proto.DefaultValue);
+ break;
+ case FieldType.Int64:
+ case FieldType.SInt64:
+ case FieldType.SFixed64:
+ defaultValue = TextFormat.ParseInt64(Proto.DefaultValue);
+ break;
+ case FieldType.UInt64:
+ case FieldType.Fixed64:
+ defaultValue = TextFormat.ParseUInt64(Proto.DefaultValue);
+ break;
+ case FieldType.Float:
+ defaultValue = TextFormat.ParseFloat(Proto.DefaultValue);
+ break;
+ case FieldType.Double:
+ defaultValue = TextFormat.ParseDouble(Proto.DefaultValue);
+ break;
+ case FieldType.Bool:
+ if (Proto.DefaultValue == "true")
+ {
+ defaultValue = true;
+ }
+ else if (Proto.DefaultValue == "false")
+ {
+ defaultValue = false;
+ }
+ else
+ {
+ throw new FormatException("Boolean values must be \"true\" or \"false\"");
+ }
+ break;
+ case FieldType.String:
+ defaultValue = Proto.DefaultValue;
+ break;
+ case FieldType.Bytes:
+ try
+ {
+ defaultValue = TextFormat.UnescapeBytes(Proto.DefaultValue);
+ }
+ catch (FormatException e)
+ {
+ throw new DescriptorValidationException(this,
+ "Couldn't parse default value: " + e.Message);
+ }
+ break;
+ case FieldType.Enum:
+ defaultValue = enumType.FindValueByName(Proto.DefaultValue);
+ if (defaultValue == null)
+ {
+ throw new DescriptorValidationException(this,
+ "Unknown enum default value: \"" +
+ Proto.DefaultValue + "\"");
+ }
+ break;
+ case FieldType.Message:
+ case FieldType.Group:
+ throw new DescriptorValidationException(this, "Message type had default value.");
+ }
+ }
+ catch (FormatException e)
+ {
+ DescriptorValidationException validationException =
+ new DescriptorValidationException(this,
+ "Could not parse default value: \"" + Proto.DefaultValue +
+ "\"", e);
+ throw validationException;
+ }
+ }
+ else
+ {
+ // Determine the default default for this field.
+ if (IsRepeated)
+ {
+ defaultValue = Lists<object>.Empty;
+ }
+ else
+ {
+ switch (MappedType)
+ {
+ case MappedType.Enum:
+ // We guarantee elsewhere that an enum type always has at least
+ // one possible value.
+ defaultValue = enumType.Values[0];
+ break;
+ case MappedType.Message:
+ defaultValue = null;
+ break;
+ default:
+ defaultValue = GetDefaultValueForMappedType(MappedType);
+ break;
+ }
+ }
+ }
+
+ if (!IsExtension)
+ {
+ File.DescriptorPool.AddFieldByNumber(this);
+ }
+
+ if (containingType != null && containingType.Options.MessageSetWireFormat)
+ {
+ if (IsExtension)
+ {
+ if (!IsOptional || FieldType != FieldType.Message)
+ {
+ throw new DescriptorValidationException(this,
+ "Extensions of MessageSets must be optional messages.");
+ }
+ }
+ else
+ {
+ throw new DescriptorValidationException(this, "MessageSets cannot have fields, only extensions.");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs b/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs index 0c933583..1c1b9be6 100644 --- a/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs +++ b/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs @@ -1,77 +1,88 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System; -using System.Collections.Generic; -using Google.ProtocolBuffers.Collections; - -namespace Google.ProtocolBuffers.Descriptors { - - /// <summary> - /// Defined specifically for the <see cref="FieldType" /> enumeration, - /// this allows each field type to specify the mapped type and wire type. - /// </summary> - [CLSCompliant(false)] - [AttributeUsage(AttributeTargets.Field)] - public sealed class FieldMappingAttribute : Attribute { - public FieldMappingAttribute(MappedType mappedType, WireFormat.WireType wireType) { - MappedType = mappedType; - WireType = wireType; - } - - public MappedType MappedType { get; private set; } - public WireFormat.WireType WireType { get; private set; } - - - /// <summary> - /// Immutable mapping from field type to mapped type. Built using the attributes on - /// FieldType values. - /// </summary> - static readonly IDictionary<FieldType, FieldMappingAttribute> FieldTypeToMappedTypeMap = MapFieldTypes(); - - private static IDictionary<FieldType, FieldMappingAttribute> MapFieldTypes() { - var map = new Dictionary<FieldType, FieldMappingAttribute>(); - foreach (System.Reflection.FieldInfo field in typeof(FieldType).GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)) { - FieldType fieldType = (FieldType)field.GetValue(null); - FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0]; - map[fieldType] = mapping; - } - return Dictionaries.AsReadOnly(map); - } - - internal static MappedType MappedTypeFromFieldType(FieldType type) { - return FieldTypeToMappedTypeMap[type].MappedType; - } - internal static WireFormat.WireType WireTypeFromFieldType(FieldType type, bool packed) { - return packed ? WireFormat.WireType.LengthDelimited : FieldTypeToMappedTypeMap[type].WireType; - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Defined specifically for the <see cref="FieldType" /> enumeration,
+ /// this allows each field type to specify the mapped type and wire type.
+ /// </summary>
+ [CLSCompliant(false)]
+ [AttributeUsage(AttributeTargets.Field)]
+ public sealed class FieldMappingAttribute : Attribute
+ {
+ public FieldMappingAttribute(MappedType mappedType, WireFormat.WireType wireType)
+ {
+ MappedType = mappedType;
+ WireType = wireType;
+ }
+
+ public MappedType MappedType { get; private set; }
+ public WireFormat.WireType WireType { get; private set; }
+
+
+ /// <summary>
+ /// Immutable mapping from field type to mapped type. Built using the attributes on
+ /// FieldType values.
+ /// </summary>
+ private static readonly IDictionary<FieldType, FieldMappingAttribute> FieldTypeToMappedTypeMap = MapFieldTypes();
+
+ private static IDictionary<FieldType, FieldMappingAttribute> MapFieldTypes()
+ {
+ var map = new Dictionary<FieldType, FieldMappingAttribute>();
+ foreach (
+ System.Reflection.FieldInfo field in
+ typeof (FieldType).GetFields(System.Reflection.BindingFlags.Static |
+ System.Reflection.BindingFlags.Public))
+ {
+ FieldType fieldType = (FieldType) field.GetValue(null);
+ FieldMappingAttribute mapping =
+ (FieldMappingAttribute) field.GetCustomAttributes(typeof (FieldMappingAttribute), false)[0];
+ map[fieldType] = mapping;
+ }
+ return Dictionaries.AsReadOnly(map);
+ }
+
+ internal static MappedType MappedTypeFromFieldType(FieldType type)
+ {
+ return FieldTypeToMappedTypeMap[type].MappedType;
+ }
+
+ internal static WireFormat.WireType WireTypeFromFieldType(FieldType type, bool packed)
+ {
+ return packed ? WireFormat.WireType.LengthDelimited : FieldTypeToMappedTypeMap[type].WireType;
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/FieldType.cs b/src/ProtocolBuffers/Descriptors/FieldType.cs index b019f888..056d3d45 100644 --- a/src/ProtocolBuffers/Descriptors/FieldType.cs +++ b/src/ProtocolBuffers/Descriptors/FieldType.cs @@ -1,58 +1,60 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Enumeration of all the possible field types. The odd formatting is to make it very clear - /// which attribute applies to which value, while maintaining a compact format. - /// </summary> - public enum FieldType { - [FieldMapping(MappedType.Double, WireFormat.WireType.Fixed64)] Double, - [FieldMapping(MappedType.Single, WireFormat.WireType.Fixed32)] Float, - [FieldMapping(MappedType.Int64, WireFormat.WireType.Varint)] Int64, - [FieldMapping(MappedType.UInt64, WireFormat.WireType.Varint)] UInt64, - [FieldMapping(MappedType.Int32, WireFormat.WireType.Varint)] Int32, - [FieldMapping(MappedType.UInt64, WireFormat.WireType.Fixed64)] Fixed64, - [FieldMapping(MappedType.UInt32, WireFormat.WireType.Fixed32)] Fixed32, - [FieldMapping(MappedType.Boolean, WireFormat.WireType.Varint)] Bool, - [FieldMapping(MappedType.String, WireFormat.WireType.LengthDelimited)] String, - [FieldMapping(MappedType.Message, WireFormat.WireType.StartGroup)] Group, - [FieldMapping(MappedType.Message, WireFormat.WireType.LengthDelimited)] Message, - [FieldMapping(MappedType.ByteString, WireFormat.WireType.LengthDelimited)] Bytes, - [FieldMapping(MappedType.UInt32, WireFormat.WireType.Varint)] UInt32, - [FieldMapping(MappedType.Int32, WireFormat.WireType.Fixed32)] SFixed32, - [FieldMapping(MappedType.Int64, WireFormat.WireType.Fixed64)] SFixed64, - [FieldMapping(MappedType.Int32, WireFormat.WireType.Varint)] SInt32, - [FieldMapping(MappedType.Int64, WireFormat.WireType.Varint)] SInt64, - [FieldMapping(MappedType.Enum, WireFormat.WireType.Varint)] Enum - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Enumeration of all the possible field types. The odd formatting is to make it very clear
+ /// which attribute applies to which value, while maintaining a compact format.
+ /// </summary>
+ public enum FieldType
+ {
+ [FieldMapping(MappedType.Double, WireFormat.WireType.Fixed64)] Double,
+ [FieldMapping(MappedType.Single, WireFormat.WireType.Fixed32)] Float,
+ [FieldMapping(MappedType.Int64, WireFormat.WireType.Varint)] Int64,
+ [FieldMapping(MappedType.UInt64, WireFormat.WireType.Varint)] UInt64,
+ [FieldMapping(MappedType.Int32, WireFormat.WireType.Varint)] Int32,
+ [FieldMapping(MappedType.UInt64, WireFormat.WireType.Fixed64)] Fixed64,
+ [FieldMapping(MappedType.UInt32, WireFormat.WireType.Fixed32)] Fixed32,
+ [FieldMapping(MappedType.Boolean, WireFormat.WireType.Varint)] Bool,
+ [FieldMapping(MappedType.String, WireFormat.WireType.LengthDelimited)] String,
+ [FieldMapping(MappedType.Message, WireFormat.WireType.StartGroup)] Group,
+ [FieldMapping(MappedType.Message, WireFormat.WireType.LengthDelimited)] Message,
+ [FieldMapping(MappedType.ByteString, WireFormat.WireType.LengthDelimited)] Bytes,
+ [FieldMapping(MappedType.UInt32, WireFormat.WireType.Varint)] UInt32,
+ [FieldMapping(MappedType.Int32, WireFormat.WireType.Fixed32)] SFixed32,
+ [FieldMapping(MappedType.Int64, WireFormat.WireType.Fixed64)] SFixed64,
+ [FieldMapping(MappedType.Int32, WireFormat.WireType.Varint)] SInt32,
+ [FieldMapping(MappedType.Int64, WireFormat.WireType.Varint)] SInt64,
+ [FieldMapping(MappedType.Enum, WireFormat.WireType.Varint)] Enum
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/FileDescriptor.cs b/src/ProtocolBuffers/Descriptors/FileDescriptor.cs index 1648c34f..392db9a7 100644 --- a/src/ProtocolBuffers/Descriptors/FileDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/FileDescriptor.cs @@ -1,432 +1,496 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using Google.ProtocolBuffers.DescriptorProtos; -using FileOptions = Google.ProtocolBuffers.DescriptorProtos.FileOptions; - -namespace Google.ProtocolBuffers.Descriptors { - /// <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 sealed class FileDescriptor : IDescriptor<FileDescriptorProto> { - private FileDescriptorProto proto; - private readonly IList<MessageDescriptor> messageTypes; - private readonly IList<EnumDescriptor> enumTypes; - private readonly IList<ServiceDescriptor> services; - private readonly IList<FieldDescriptor> extensions; - private readonly IList<FileDescriptor> dependencies; - private readonly DescriptorPool pool; - private CSharpFileOptions csharpFileOptions; - private readonly object optionsLock = new object(); - - private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool) { - this.pool = pool; - this.proto = proto; - this.dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone()); - - pool.AddPackage(Package, this); - - messageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageTypeList, - (message, index) => - new MessageDescriptor(message, this, null, index)); - - enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumTypeList, - (enumType, index) => - new EnumDescriptor(enumType, this, null, index)); - - services = DescriptorUtil.ConvertAndMakeReadOnly(proto.ServiceList, - (service, index) => new ServiceDescriptor(service, this, index)); - - extensions = DescriptorUtil.ConvertAndMakeReadOnly(proto.ExtensionList, - (field, index) => - new FieldDescriptor(field, this, null, index, true)); - } - - - /// <summary> - /// Allows a file descriptor to be configured with a set of external options, e.g. from the - /// command-line arguments to protogen. - /// </summary> - public void ConfigureWithDefaultOptions(CSharpFileOptions options) { - csharpFileOptions = BuildOrFakeWithDefaultOptions(options); - } - - private CSharpFileOptions BuildOrFakeWithDefaultOptions(CSharpFileOptions defaultOptions) { - // Fix for being able to relocate these files to any directory structure - if (proto.Package == "google.protobuf") { - string filename = Path.GetFileName(proto.Name); - // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues) - if (filename == "descriptor.proto") { - return new CSharpFileOptions.Builder { - Namespace = "Google.ProtocolBuffers.DescriptorProtos", - UmbrellaClassname = "DescriptorProtoFile", - NestClasses = false, - MultipleFiles = false, - PublicClasses = true, - OutputDirectory = defaultOptions.OutputDirectory, - IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf - }.Build(); - } - if (filename == "csharp_options.proto") { - return new CSharpFileOptions.Builder { - Namespace = "Google.ProtocolBuffers.DescriptorProtos", - UmbrellaClassname = "CSharpOptions", - NestClasses = false, - MultipleFiles = false, - PublicClasses = true, - OutputDirectory = defaultOptions.OutputDirectory, - IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf - }.Build(); - } - } - CSharpFileOptions.Builder builder = defaultOptions.ToBuilder(); - if (proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions)) { - builder.MergeFrom(proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions)); - } - if (!builder.HasNamespace) { - builder.Namespace = Package; - } - if (!builder.HasUmbrellaClassname) { - int lastSlash = Name.LastIndexOf('/'); - string baseName = Name.Substring(lastSlash + 1); - builder.UmbrellaClassname = NameHelpers.UnderscoresToPascalCase(NameHelpers.StripProto(baseName)); - } - - // Auto-fix for name collision by placing umbrella class into a new namespace. This - // still won't fix the collisions with nesting enabled; however, you have to turn that on explicitly anyway. - if (!builder.NestClasses && !builder.HasUmbrellaNamespace) { - bool collision = false; - foreach (IDescriptor d in MessageTypes) { - collision |= d.Name == builder.UmbrellaClassname; - } - foreach (IDescriptor d in Services) { - collision |= d.Name == builder.UmbrellaClassname; - } - foreach (IDescriptor d in EnumTypes) { - collision |= d.Name == builder.UmbrellaClassname; - } - if (collision) { - builder.UmbrellaNamespace = "Proto"; - } - } - - return builder.Build(); - } - - /// <value> - /// The descriptor in its protocol message representation. - /// </value> - public FileDescriptorProto Proto { - get { return proto; } - } - - /// <value> - /// The <see cref="DescriptorProtos.FileOptions" /> defined in <c>descriptor.proto</c>. - /// </value> - public FileOptions Options { - get { return proto.Options; } - } - - /// <summary> - /// Returns the C#-specific options for this file descriptor. This will always be - /// completely filled in. - /// </summary> - public CSharpFileOptions CSharpOptions { - get { - lock (optionsLock) { - if (csharpFileOptions == null) { - csharpFileOptions = BuildOrFakeWithDefaultOptions(CSharpFileOptions.DefaultInstance); - } - } - return csharpFileOptions; - } - } - - /// <value> - /// The file name. - /// </value> - public string Name { - get { return proto.Name; } - } - - /// <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 string Package { - get { return proto.Package; } - } - - /// <value> - /// Unmodifiable list of top-level message types declared in this file. - /// </value> - public IList<MessageDescriptor> MessageTypes { - get { return messageTypes; } - } - - /// <value> - /// Unmodifiable list of top-level enum types declared in this file. - /// </value> - public IList<EnumDescriptor> EnumTypes { - get { return enumTypes; } - } - - /// <value> - /// Unmodifiable list of top-level services declared in this file. - /// </value> - public IList<ServiceDescriptor> Services { - get { return services; } - } - - /// <value> - /// Unmodifiable list of top-level extensions declared in this file. - /// </value> - public IList<FieldDescriptor> Extensions { - get { return extensions; } - } - - /// <value> - /// Unmodifiable list of this file's dependencies (imports). - /// </value> - public IList<FileDescriptor> Dependencies { - get { return dependencies; } - } - - /// <value> - /// Implementation of IDescriptor.FullName - just returns the same as Name. - /// </value> - string IDescriptor.FullName { - get { return Name; } - } - - /// <value> - /// Implementation of IDescriptor.File - just returns this descriptor. - /// </value> - FileDescriptor IDescriptor.File { - get { return this; } - } - - /// <value> - /// Protocol buffer describing this descriptor. - /// </value> - IMessage IDescriptor.Proto { - get { return Proto; } - } - - /// <value> - /// Pool containing symbol descriptors. - /// </value> - internal DescriptorPool DescriptorPool { - get { return pool; } - } - - /// <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 (or ITypeDescriptor for any)</typeparam> - /// <returns>The type's descriptor, or null if not found.</returns> - public T FindTypeByName<T>(String name) - where T : class, IDescriptor { - // Don't allow looking up nested types. This will make optimization - // easier later. - if (name.IndexOf('.') != -1) { - return null; - } - if (Package.Length > 0) { - name = Package + "." + name; - } - T result = pool.FindSymbol<T>(name); - if (result != null && result.File == this) { - return result; - } - return null; - } - - /// <summary> - /// Builds a FileDescriptor from its protocol buffer representation. - /// </summary> - /// <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> - /// <exception cref="DescriptorValidationException">If <paramref name="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> - public static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies) { - // 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 == null) { - dependencies = new FileDescriptor[0]; - } - - DescriptorPool pool = new DescriptorPool(dependencies); - FileDescriptor result = new FileDescriptor(proto, dependencies, pool); - - if (dependencies.Length != proto.DependencyCount) { - throw new DescriptorValidationException(result, - "Dependencies passed to FileDescriptor.BuildFrom() don't match " + - "those listed in the FileDescriptorProto."); - } - for (int i = 0; i < proto.DependencyCount; i++) { - if (dependencies[i].Name != proto.DependencyList[i]) { - throw new DescriptorValidationException(result, - "Dependencies passed to FileDescriptor.BuildFrom() don't match " + - "those listed in the FileDescriptorProto."); - } - } - - result.CrossLink(); - return result; - } - - private void CrossLink() { - foreach (MessageDescriptor message in messageTypes) { - message.CrossLink(); - } - - foreach (ServiceDescriptor service in services) { - service.CrossLink(); - } - - foreach (FieldDescriptor extension in extensions) { - extension.CrossLink(); - } - - foreach (MessageDescriptor message in messageTypes) { - message.CheckRequiredFields(); - } - } - - /// <summary> - /// This method is to be called by generated code only. It is equivalent - /// to BuildFrom except that the FileDescriptorProto is encoded in - /// protocol buffer wire format. This overload is maintained for backward - /// compatibility with source code generated before the custom options were available - /// (and working). - /// </summary> - public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, FileDescriptor[] dependencies) { - return InternalBuildGeneratedFileFrom(descriptorData, dependencies, x => null); - } - - /// <summary> - /// This delegate should be used by generated code only. When calling - /// FileDescriptor.InternalBuildGeneratedFileFrom, the caller can provide - /// a callback which assigns the global variables defined in the generated code - /// which point at parts of the FileDescriptor. The callback returns an - /// Extension Registry which contains any extensions which might be used in - /// the descriptor - that is, extensions of the various "Options" messages defined - /// in descriptor.proto. The callback may also return null to indicate that - /// no extensions are used in the descriptor. - /// </summary> - /// <param name="descriptor"></param> - /// <returns></returns> - public delegate ExtensionRegistry InternalDescriptorAssigner(FileDescriptor descriptor); - - public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, - FileDescriptor[] dependencies, - InternalDescriptorAssigner descriptorAssigner) { - FileDescriptorProto proto; - try { - proto = FileDescriptorProto.ParseFrom(descriptorData); - } - catch (InvalidProtocolBufferException e) { - throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e); - } - - FileDescriptor result; - try { - result = BuildFrom(proto, dependencies); - } - catch (DescriptorValidationException e) { - throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e); - } - - ExtensionRegistry registry = descriptorAssigner(result); - - if (registry != null) { - // We must re-parse the proto using the registry. - try { - proto = FileDescriptorProto.ParseFrom(descriptorData, registry); - } - catch (InvalidProtocolBufferException e) { - throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e); - } - - result.ReplaceProto(proto); - } - return result; - } - - /// <summary> - /// Replace our FileDescriptorProto with the given one, which is - /// identical except that it might contain extensions that weren't present - /// in the original. This method is needed for bootstrapping when a file - /// defines custom options. The options may be defined in the file itself, - /// so we can't actually parse them until we've constructed the descriptors, - /// but to construct the decsriptors we have to have parsed the descriptor - /// protos. So, we have to parse the descriptor protos a second time after - /// constructing the descriptors. - /// </summary> - private void ReplaceProto(FileDescriptorProto newProto) { - proto = newProto; - - for (int i = 0; i < messageTypes.Count; i++) { - messageTypes[i].ReplaceProto(proto.GetMessageType(i)); - } - - for (int i = 0; i < enumTypes.Count; i++) { - enumTypes[i].ReplaceProto(proto.GetEnumType(i)); - } - - for (int i = 0; i < services.Count; i++) { - services[i].ReplaceProto(proto.GetService(i)); - } - - for (int i = 0; i < extensions.Count; i++) { - extensions[i].ReplaceProto(proto.GetExtension(i)); - } - } - } +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using Google.ProtocolBuffers.DescriptorProtos;
+using FileOptions = Google.ProtocolBuffers.DescriptorProtos.FileOptions;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <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 sealed class FileDescriptor : IDescriptor<FileDescriptorProto>
+ {
+ private FileDescriptorProto proto;
+ private readonly IList<MessageDescriptor> messageTypes;
+ private readonly IList<EnumDescriptor> enumTypes;
+ private readonly IList<ServiceDescriptor> services;
+ private readonly IList<FieldDescriptor> extensions;
+ private readonly IList<FileDescriptor> dependencies;
+ private readonly DescriptorPool pool;
+ private CSharpFileOptions csharpFileOptions;
+ private readonly object optionsLock = new object();
+
+ private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool)
+ {
+ this.pool = pool;
+ this.proto = proto;
+ this.dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone());
+
+ pool.AddPackage(Package, this);
+
+ messageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageTypeList,
+ (message, index) =>
+ new MessageDescriptor(message, this, null, index));
+
+ enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumTypeList,
+ (enumType, index) =>
+ new EnumDescriptor(enumType, this, null, index));
+
+ services = DescriptorUtil.ConvertAndMakeReadOnly(proto.ServiceList,
+ (service, index) =>
+ new ServiceDescriptor(service, this, index));
+
+ extensions = DescriptorUtil.ConvertAndMakeReadOnly(proto.ExtensionList,
+ (field, index) =>
+ new FieldDescriptor(field, this, null, index, true));
+ }
+
+
+ /// <summary>
+ /// Allows a file descriptor to be configured with a set of external options, e.g. from the
+ /// command-line arguments to protogen.
+ /// </summary>
+ public void ConfigureWithDefaultOptions(CSharpFileOptions options)
+ {
+ csharpFileOptions = BuildOrFakeWithDefaultOptions(options);
+ }
+
+ private CSharpFileOptions BuildOrFakeWithDefaultOptions(CSharpFileOptions defaultOptions)
+ {
+ // Fix for being able to relocate these files to any directory structure
+ if (proto.Package == "google.protobuf")
+ {
+ string filename = Path.GetFileName(proto.Name);
+ // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues)
+ if (filename == "descriptor.proto")
+ {
+ return new CSharpFileOptions.Builder
+ {
+ Namespace = "Google.ProtocolBuffers.DescriptorProtos",
+ UmbrellaClassname = "DescriptorProtoFile",
+ NestClasses = false,
+ MultipleFiles = false,
+ PublicClasses = true,
+ OutputDirectory = defaultOptions.OutputDirectory,
+ IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf
+ }.Build();
+ }
+ if (filename == "csharp_options.proto")
+ {
+ return new CSharpFileOptions.Builder
+ {
+ Namespace = "Google.ProtocolBuffers.DescriptorProtos",
+ UmbrellaClassname = "CSharpOptions",
+ NestClasses = false,
+ MultipleFiles = false,
+ PublicClasses = true,
+ OutputDirectory = defaultOptions.OutputDirectory,
+ IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf
+ }.Build();
+ }
+ }
+ CSharpFileOptions.Builder builder = defaultOptions.ToBuilder();
+ if (proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions))
+ {
+ builder.MergeFrom(proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions));
+ }
+ if (!builder.HasNamespace)
+ {
+ builder.Namespace = Package;
+ }
+ if (!builder.HasUmbrellaClassname)
+ {
+ int lastSlash = Name.LastIndexOf('/');
+ string baseName = Name.Substring(lastSlash + 1);
+ builder.UmbrellaClassname = NameHelpers.UnderscoresToPascalCase(NameHelpers.StripProto(baseName));
+ }
+
+ // Auto-fix for name collision by placing umbrella class into a new namespace. This
+ // still won't fix the collisions with nesting enabled; however, you have to turn that on explicitly anyway.
+ if (!builder.NestClasses && !builder.HasUmbrellaNamespace)
+ {
+ bool collision = false;
+ foreach (IDescriptor d in MessageTypes)
+ {
+ collision |= d.Name == builder.UmbrellaClassname;
+ }
+ foreach (IDescriptor d in Services)
+ {
+ collision |= d.Name == builder.UmbrellaClassname;
+ }
+ foreach (IDescriptor d in EnumTypes)
+ {
+ collision |= d.Name == builder.UmbrellaClassname;
+ }
+ if (collision)
+ {
+ builder.UmbrellaNamespace = "Proto";
+ }
+ }
+
+ return builder.Build();
+ }
+
+ /// <value>
+ /// The descriptor in its protocol message representation.
+ /// </value>
+ public FileDescriptorProto Proto
+ {
+ get { return proto; }
+ }
+
+ /// <value>
+ /// The <see cref="DescriptorProtos.FileOptions" /> defined in <c>descriptor.proto</c>.
+ /// </value>
+ public FileOptions Options
+ {
+ get { return proto.Options; }
+ }
+
+ /// <summary>
+ /// Returns the C#-specific options for this file descriptor. This will always be
+ /// completely filled in.
+ /// </summary>
+ public CSharpFileOptions CSharpOptions
+ {
+ get
+ {
+ lock (optionsLock)
+ {
+ if (csharpFileOptions == null)
+ {
+ csharpFileOptions = BuildOrFakeWithDefaultOptions(CSharpFileOptions.DefaultInstance);
+ }
+ }
+ return csharpFileOptions;
+ }
+ }
+
+ /// <value>
+ /// The file name.
+ /// </value>
+ public string Name
+ {
+ get { return proto.Name; }
+ }
+
+ /// <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 string Package
+ {
+ get { return proto.Package; }
+ }
+
+ /// <value>
+ /// Unmodifiable list of top-level message types declared in this file.
+ /// </value>
+ public IList<MessageDescriptor> MessageTypes
+ {
+ get { return messageTypes; }
+ }
+
+ /// <value>
+ /// Unmodifiable list of top-level enum types declared in this file.
+ /// </value>
+ public IList<EnumDescriptor> EnumTypes
+ {
+ get { return enumTypes; }
+ }
+
+ /// <value>
+ /// Unmodifiable list of top-level services declared in this file.
+ /// </value>
+ public IList<ServiceDescriptor> Services
+ {
+ get { return services; }
+ }
+
+ /// <value>
+ /// Unmodifiable list of top-level extensions declared in this file.
+ /// </value>
+ public IList<FieldDescriptor> Extensions
+ {
+ get { return extensions; }
+ }
+
+ /// <value>
+ /// Unmodifiable list of this file's dependencies (imports).
+ /// </value>
+ public IList<FileDescriptor> Dependencies
+ {
+ get { return dependencies; }
+ }
+
+ /// <value>
+ /// Implementation of IDescriptor.FullName - just returns the same as Name.
+ /// </value>
+ string IDescriptor.FullName
+ {
+ get { return Name; }
+ }
+
+ /// <value>
+ /// Implementation of IDescriptor.File - just returns this descriptor.
+ /// </value>
+ FileDescriptor IDescriptor.File
+ {
+ get { return this; }
+ }
+
+ /// <value>
+ /// Protocol buffer describing this descriptor.
+ /// </value>
+ IMessage IDescriptor.Proto
+ {
+ get { return Proto; }
+ }
+
+ /// <value>
+ /// Pool containing symbol descriptors.
+ /// </value>
+ internal DescriptorPool DescriptorPool
+ {
+ get { return pool; }
+ }
+
+ /// <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 (or ITypeDescriptor for any)</typeparam>
+ /// <returns>The type's descriptor, or null if not found.</returns>
+ public T FindTypeByName<T>(String name)
+ where T : class, IDescriptor
+ {
+ // Don't allow looking up nested types. This will make optimization
+ // easier later.
+ if (name.IndexOf('.') != -1)
+ {
+ return null;
+ }
+ if (Package.Length > 0)
+ {
+ name = Package + "." + name;
+ }
+ T result = pool.FindSymbol<T>(name);
+ if (result != null && result.File == this)
+ {
+ return result;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Builds a FileDescriptor from its protocol buffer representation.
+ /// </summary>
+ /// <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>
+ /// <exception cref="DescriptorValidationException">If <paramref name="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>
+ public static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies)
+ {
+ // 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 == null)
+ {
+ dependencies = new FileDescriptor[0];
+ }
+
+ DescriptorPool pool = new DescriptorPool(dependencies);
+ FileDescriptor result = new FileDescriptor(proto, dependencies, pool);
+
+ if (dependencies.Length != proto.DependencyCount)
+ {
+ throw new DescriptorValidationException(result,
+ "Dependencies passed to FileDescriptor.BuildFrom() don't match " +
+ "those listed in the FileDescriptorProto.");
+ }
+ for (int i = 0; i < proto.DependencyCount; i++)
+ {
+ if (dependencies[i].Name != proto.DependencyList[i])
+ {
+ throw new DescriptorValidationException(result,
+ "Dependencies passed to FileDescriptor.BuildFrom() don't match " +
+ "those listed in the FileDescriptorProto.");
+ }
+ }
+
+ result.CrossLink();
+ return result;
+ }
+
+ private void CrossLink()
+ {
+ foreach (MessageDescriptor message in messageTypes)
+ {
+ message.CrossLink();
+ }
+
+ foreach (ServiceDescriptor service in services)
+ {
+ service.CrossLink();
+ }
+
+ foreach (FieldDescriptor extension in extensions)
+ {
+ extension.CrossLink();
+ }
+
+ foreach (MessageDescriptor message in messageTypes)
+ {
+ message.CheckRequiredFields();
+ }
+ }
+
+ /// <summary>
+ /// This method is to be called by generated code only. It is equivalent
+ /// to BuildFrom except that the FileDescriptorProto is encoded in
+ /// protocol buffer wire format. This overload is maintained for backward
+ /// compatibility with source code generated before the custom options were available
+ /// (and working).
+ /// </summary>
+ public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, FileDescriptor[] dependencies)
+ {
+ return InternalBuildGeneratedFileFrom(descriptorData, dependencies, x => null);
+ }
+
+ /// <summary>
+ /// This delegate should be used by generated code only. When calling
+ /// FileDescriptor.InternalBuildGeneratedFileFrom, the caller can provide
+ /// a callback which assigns the global variables defined in the generated code
+ /// which point at parts of the FileDescriptor. The callback returns an
+ /// Extension Registry which contains any extensions which might be used in
+ /// the descriptor - that is, extensions of the various "Options" messages defined
+ /// in descriptor.proto. The callback may also return null to indicate that
+ /// no extensions are used in the descriptor.
+ /// </summary>
+ /// <param name="descriptor"></param>
+ /// <returns></returns>
+ public delegate ExtensionRegistry InternalDescriptorAssigner(FileDescriptor descriptor);
+
+ public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData,
+ FileDescriptor[] dependencies,
+ InternalDescriptorAssigner descriptorAssigner)
+ {
+ FileDescriptorProto proto;
+ try
+ {
+ proto = FileDescriptorProto.ParseFrom(descriptorData);
+ }
+ catch (InvalidProtocolBufferException e)
+ {
+ throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e);
+ }
+
+ FileDescriptor result;
+ try
+ {
+ result = BuildFrom(proto, dependencies);
+ }
+ catch (DescriptorValidationException e)
+ {
+ throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e);
+ }
+
+ ExtensionRegistry registry = descriptorAssigner(result);
+
+ if (registry != null)
+ {
+ // We must re-parse the proto using the registry.
+ try
+ {
+ proto = FileDescriptorProto.ParseFrom(descriptorData, registry);
+ }
+ catch (InvalidProtocolBufferException e)
+ {
+ throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e);
+ }
+
+ result.ReplaceProto(proto);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Replace our FileDescriptorProto with the given one, which is
+ /// identical except that it might contain extensions that weren't present
+ /// in the original. This method is needed for bootstrapping when a file
+ /// defines custom options. The options may be defined in the file itself,
+ /// so we can't actually parse them until we've constructed the descriptors,
+ /// but to construct the decsriptors we have to have parsed the descriptor
+ /// protos. So, we have to parse the descriptor protos a second time after
+ /// constructing the descriptors.
+ /// </summary>
+ private void ReplaceProto(FileDescriptorProto newProto)
+ {
+ proto = newProto;
+
+ for (int i = 0; i < messageTypes.Count; i++)
+ {
+ messageTypes[i].ReplaceProto(proto.GetMessageType(i));
+ }
+
+ for (int i = 0; i < enumTypes.Count; i++)
+ {
+ enumTypes[i].ReplaceProto(proto.GetEnumType(i));
+ }
+
+ for (int i = 0; i < services.Count; i++)
+ {
+ services[i].ReplaceProto(proto.GetService(i));
+ }
+
+ for (int i = 0; i < extensions.Count; i++)
+ {
+ extensions[i].ReplaceProto(proto.GetExtension(i));
+ }
+ }
+ }
}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/IDescriptor.cs b/src/ProtocolBuffers/Descriptors/IDescriptor.cs index 937dd7e7..899c1560 100644 --- a/src/ProtocolBuffers/Descriptors/IDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/IDescriptor.cs @@ -1,53 +1,55 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -namespace Google.ProtocolBuffers.Descriptors { - - /// <summary> - /// The non-generic form of the IDescriptor interface. Useful for describing a general - /// descriptor. - /// </summary> - public interface IDescriptor { - string Name { get; } - string FullName { get; } - FileDescriptor File { get; } - IMessage Proto { get; } - } - - /// <summary> - /// Strongly-typed form of the IDescriptor interface. - /// </summary> - /// <typeparam name="TProto">Protocol buffer type underlying this descriptor type</typeparam> - public interface IDescriptor<TProto> : IDescriptor where TProto : IMessage { - new TProto Proto { get; } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// The non-generic form of the IDescriptor interface. Useful for describing a general
+ /// descriptor.
+ /// </summary>
+ public interface IDescriptor
+ {
+ string Name { get; }
+ string FullName { get; }
+ FileDescriptor File { get; }
+ IMessage Proto { get; }
+ }
+
+ /// <summary>
+ /// Strongly-typed form of the IDescriptor interface.
+ /// </summary>
+ /// <typeparam name="TProto">Protocol buffer type underlying this descriptor type</typeparam>
+ public interface IDescriptor<TProto> : IDescriptor where TProto : IMessage
+ {
+ new TProto Proto { get; }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs b/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs index 50842d1f..bdb4eb82 100644 --- a/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs +++ b/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs @@ -1,61 +1,64 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Base class for descriptors which are also indexed. This is all of them other than - /// <see cref="FileDescriptor" />. - /// </summary> - public abstract class IndexedDescriptorBase<TProto, TOptions> : DescriptorBase<TProto, TOptions> - where TProto : IMessage<TProto>, IDescriptorProto<TOptions> { - - private readonly int index; - - protected IndexedDescriptorBase(TProto proto, FileDescriptor file, string fullName, int index) - : base(proto, file, fullName) { - this.index = index; - } - - /// <value> - /// The index of this descriptor within its parent descriptor. - /// </value> - /// <remarks> - /// This returns the index of this descriptor within its parent, for - /// this descriptor's type. (There can be duplicate values for different - /// types, e.g. one enum type with index 0 and one message type with index 0.) - /// </remarks> - public int Index { - get { return index; } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Base class for descriptors which are also indexed. This is all of them other than
+ /// <see cref="FileDescriptor" />.
+ /// </summary>
+ public abstract class IndexedDescriptorBase<TProto, TOptions> : DescriptorBase<TProto, TOptions>
+ where TProto : IMessage<TProto>, IDescriptorProto<TOptions>
+ {
+ private readonly int index;
+
+ protected IndexedDescriptorBase(TProto proto, FileDescriptor file, string fullName, int index)
+ : base(proto, file, fullName)
+ {
+ this.index = index;
+ }
+
+ /// <value>
+ /// The index of this descriptor within its parent descriptor.
+ /// </value>
+ /// <remarks>
+ /// This returns the index of this descriptor within its parent, for
+ /// this descriptor's type. (There can be duplicate values for different
+ /// types, e.g. one enum type with index 0 and one message type with index 0.)
+ /// </remarks>
+ public int Index
+ {
+ get { return index; }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/MappedType.cs b/src/ProtocolBuffers/Descriptors/MappedType.cs index aee3fa8d..0a555307 100644 --- a/src/ProtocolBuffers/Descriptors/MappedType.cs +++ b/src/ProtocolBuffers/Descriptors/MappedType.cs @@ -1,50 +1,52 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Type as it's mapped onto a .NET type. - /// </summary> - public enum MappedType { - Int32, - Int64, - UInt32, - UInt64, - Single, - Double, - Boolean, - String, - ByteString, - Message, - Enum - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Type as it's mapped onto a .NET type.
+ /// </summary>
+ public enum MappedType
+ {
+ Int32,
+ Int64,
+ UInt32,
+ UInt64,
+ Single,
+ Double,
+ Boolean,
+ String,
+ ByteString,
+ Message,
+ Enum
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs b/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs index 79356170..d438c0ff 100644 --- a/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs @@ -1,252 +1,288 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System; -using System.Collections.Generic; -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - - /// <summary> - /// Describes a message type. - /// </summary> - public sealed class MessageDescriptor : IndexedDescriptorBase<DescriptorProto, MessageOptions> { - - private readonly MessageDescriptor containingType; - private readonly IList<MessageDescriptor> nestedTypes; - private readonly IList<EnumDescriptor> enumTypes; - private readonly IList<FieldDescriptor> fields; - private readonly IList<FieldDescriptor> extensions; - private bool hasRequiredFields; - - internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex) - : base(proto, file, ComputeFullName(file, parent, proto.Name), typeIndex) { - containingType = parent; - - nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedTypeList, - (type, index) => new MessageDescriptor(type, file, this, index)); - - enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumTypeList, - (type, index) => new EnumDescriptor(type, file, this, index)); - - // TODO(jonskeet): Sort fields first? - fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.FieldList, - (field, index) => new FieldDescriptor(field, file, this, index, false)); - - extensions = DescriptorUtil.ConvertAndMakeReadOnly(proto.ExtensionList, - (field, index) => new FieldDescriptor(field, file, this, index, true)); - - file.DescriptorPool.AddSymbol(this); - } - - /// <value> - /// If this is a nested type, get the outer descriptor, otherwise null. - /// </value> - public MessageDescriptor ContainingType { - get { return containingType; } - } - - /// <value> - /// An unmodifiable list of this message type's fields. - /// </value> - public IList<FieldDescriptor> Fields { - get { return fields; } - } - - /// <value> - /// An unmodifiable list of this message type's extensions. - /// </value> - public IList<FieldDescriptor> Extensions { - get { return extensions; } - } - - /// <value> - /// An unmodifiable list of this message type's nested types. - /// </value> - public IList<MessageDescriptor> NestedTypes { - get { return nestedTypes; } - } - - /// <value> - /// An unmodifiable list of this message type's enum types. - /// </value> - public IList<EnumDescriptor> EnumTypes { - get { return enumTypes; } - } - - /// <summary> - /// Returns a pre-computed result as to whether this message - /// has required fields. This includes optional fields which are - /// message types which in turn have required fields, and any - /// extension fields. - /// </summary> - internal bool HasRequiredFields { - get { return hasRequiredFields; } - } - - /// <summary> - /// Determines if the given field number is an extension. - /// </summary> - public bool IsExtensionNumber(int number) { - foreach (DescriptorProto.Types.ExtensionRange range in Proto.ExtensionRangeList) { - if (range.Start <= number && number < range.End) { - return true; - } - } - return false; - } - - /// <summary> - /// Finds a field by field name. - /// </summary> - /// <param name="name">The unqualified name of the field (e.g. "foo").</param> - /// <returns>The field's descriptor, or null if not found.</returns> - public FieldDescriptor FindFieldByName(String name) { - return File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name); - } - - /// <summary> - /// Finds a field by field number. - /// </summary> - /// <param name="number">The field number within this message type.</param> - /// <returns>The field's descriptor, or null if not found.</returns> - public FieldDescriptor FindFieldByNumber(int number) { - return File.DescriptorPool.FindFieldByNumber(this, number); - } - - /// <summary> - /// Finds a field by its property name, as it would be generated by protogen. - /// </summary> - /// <param name="propertyName">The property name within this message type.</param> - /// <returns>The field's descriptor, or null if not found.</returns> - public FieldDescriptor FindFieldByPropertyName(string propertyName) { - // For reasonably short messages, this will be more efficient than a dictionary - // lookup. It also means we don't need to do things lazily with locks etc. - foreach (FieldDescriptor field in Fields) { - if (field.CSharpOptions.PropertyName == propertyName) { - return field; - } - } - return null; - } - - /// <summary> - /// Finds a nested descriptor by name. The is valid for fields, nested - /// message types and enums. - /// </summary> - /// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param> - /// <returns>The descriptor, or null if not found.</returns> - public T FindDescriptor<T>(string name) - where T : class, IDescriptor { - return File.DescriptorPool.FindSymbol<T>(FullName + "." + name); - } - - /// <summary> - /// Looks up and cross-links all fields, nested types, and extensions. - /// </summary> - internal void CrossLink() { - foreach (MessageDescriptor message in nestedTypes) { - message.CrossLink(); - } - - foreach (FieldDescriptor field in fields) { - field.CrossLink(); - } - - foreach (FieldDescriptor extension in extensions) { - extension.CrossLink(); - } - } - - internal void CheckRequiredFields() { - IDictionary<MessageDescriptor, byte> alreadySeen = new Dictionary<MessageDescriptor, byte>(); - hasRequiredFields = CheckRequiredFields(alreadySeen); - } - - private bool CheckRequiredFields(IDictionary<MessageDescriptor,byte> alreadySeen) { - - if (alreadySeen.ContainsKey(this)) { - // The type is already in the cache. This means that either: - // a. The type has no required fields. - // b. We are in the midst of checking if the type has required fields, - // somewhere up the stack. In this case, we know that if the type - // has any required fields, they'll be found when we return to it, - // and the whole call to HasRequiredFields() will return true. - // Therefore, we don't have to check if this type has required fields - // here. - return false; - } - alreadySeen[this] = 0; // Value is irrelevant; we want set semantics - - // If the type allows extensions, an extension with message type could contain - // required fields, so we have to be conservative and assume such an - // extension exists. - if (Proto.ExtensionRangeCount != 0) { - return true; - } - - foreach (FieldDescriptor field in Fields) { - if (field.IsRequired) { - return true; - } - if (field.MappedType == MappedType.Message) { - if (field.MessageType.CheckRequiredFields(alreadySeen)) { - return true; - } - } - } - return false; - } - - /// <summary> - /// See FileDescriptor.ReplaceProto - /// </summary> - internal override void ReplaceProto(DescriptorProto newProto) { - base.ReplaceProto(newProto); - - for (int i = 0; i < nestedTypes.Count; i++) { - nestedTypes[i].ReplaceProto(newProto.GetNestedType(i)); - } - - for (int i = 0; i < enumTypes.Count; i++) { - enumTypes[i].ReplaceProto(newProto.GetEnumType(i)); - } - - for (int i = 0; i < fields.Count; i++) { - fields[i].ReplaceProto(newProto.GetField(i)); - } - - for (int i = 0; i < extensions.Count; i++) { - extensions[i].ReplaceProto(newProto.GetExtension(i)); - } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Describes a message type.
+ /// </summary>
+ public sealed class MessageDescriptor : IndexedDescriptorBase<DescriptorProto, MessageOptions>
+ {
+ private readonly MessageDescriptor containingType;
+ private readonly IList<MessageDescriptor> nestedTypes;
+ private readonly IList<EnumDescriptor> enumTypes;
+ private readonly IList<FieldDescriptor> fields;
+ private readonly IList<FieldDescriptor> extensions;
+ private bool hasRequiredFields;
+
+ internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex)
+ : base(proto, file, ComputeFullName(file, parent, proto.Name), typeIndex)
+ {
+ containingType = parent;
+
+ nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedTypeList,
+ (type, index) =>
+ new MessageDescriptor(type, file, this, index));
+
+ enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumTypeList,
+ (type, index) =>
+ new EnumDescriptor(type, file, this, index));
+
+ // TODO(jonskeet): Sort fields first?
+ fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.FieldList,
+ (field, index) =>
+ new FieldDescriptor(field, file, this, index, false));
+
+ extensions = DescriptorUtil.ConvertAndMakeReadOnly(proto.ExtensionList,
+ (field, index) =>
+ new FieldDescriptor(field, file, this, index, true));
+
+ file.DescriptorPool.AddSymbol(this);
+ }
+
+ /// <value>
+ /// If this is a nested type, get the outer descriptor, otherwise null.
+ /// </value>
+ public MessageDescriptor ContainingType
+ {
+ get { return containingType; }
+ }
+
+ /// <value>
+ /// An unmodifiable list of this message type's fields.
+ /// </value>
+ public IList<FieldDescriptor> Fields
+ {
+ get { return fields; }
+ }
+
+ /// <value>
+ /// An unmodifiable list of this message type's extensions.
+ /// </value>
+ public IList<FieldDescriptor> Extensions
+ {
+ get { return extensions; }
+ }
+
+ /// <value>
+ /// An unmodifiable list of this message type's nested types.
+ /// </value>
+ public IList<MessageDescriptor> NestedTypes
+ {
+ get { return nestedTypes; }
+ }
+
+ /// <value>
+ /// An unmodifiable list of this message type's enum types.
+ /// </value>
+ public IList<EnumDescriptor> EnumTypes
+ {
+ get { return enumTypes; }
+ }
+
+ /// <summary>
+ /// Returns a pre-computed result as to whether this message
+ /// has required fields. This includes optional fields which are
+ /// message types which in turn have required fields, and any
+ /// extension fields.
+ /// </summary>
+ internal bool HasRequiredFields
+ {
+ get { return hasRequiredFields; }
+ }
+
+ /// <summary>
+ /// Determines if the given field number is an extension.
+ /// </summary>
+ public bool IsExtensionNumber(int number)
+ {
+ foreach (DescriptorProto.Types.ExtensionRange range in Proto.ExtensionRangeList)
+ {
+ if (range.Start <= number && number < range.End)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Finds a field by field name.
+ /// </summary>
+ /// <param name="name">The unqualified name of the field (e.g. "foo").</param>
+ /// <returns>The field's descriptor, or null if not found.</returns>
+ public FieldDescriptor FindFieldByName(String name)
+ {
+ return File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name);
+ }
+
+ /// <summary>
+ /// Finds a field by field number.
+ /// </summary>
+ /// <param name="number">The field number within this message type.</param>
+ /// <returns>The field's descriptor, or null if not found.</returns>
+ public FieldDescriptor FindFieldByNumber(int number)
+ {
+ return File.DescriptorPool.FindFieldByNumber(this, number);
+ }
+
+ /// <summary>
+ /// Finds a field by its property name, as it would be generated by protogen.
+ /// </summary>
+ /// <param name="propertyName">The property name within this message type.</param>
+ /// <returns>The field's descriptor, or null if not found.</returns>
+ public FieldDescriptor FindFieldByPropertyName(string propertyName)
+ {
+ // For reasonably short messages, this will be more efficient than a dictionary
+ // lookup. It also means we don't need to do things lazily with locks etc.
+ foreach (FieldDescriptor field in Fields)
+ {
+ if (field.CSharpOptions.PropertyName == propertyName)
+ {
+ return field;
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Finds a nested descriptor by name. The is valid for fields, nested
+ /// message types and enums.
+ /// </summary>
+ /// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param>
+ /// <returns>The descriptor, or null if not found.</returns>
+ public T FindDescriptor<T>(string name)
+ where T : class, IDescriptor
+ {
+ return File.DescriptorPool.FindSymbol<T>(FullName + "." + name);
+ }
+
+ /// <summary>
+ /// Looks up and cross-links all fields, nested types, and extensions.
+ /// </summary>
+ internal void CrossLink()
+ {
+ foreach (MessageDescriptor message in nestedTypes)
+ {
+ message.CrossLink();
+ }
+
+ foreach (FieldDescriptor field in fields)
+ {
+ field.CrossLink();
+ }
+
+ foreach (FieldDescriptor extension in extensions)
+ {
+ extension.CrossLink();
+ }
+ }
+
+ internal void CheckRequiredFields()
+ {
+ IDictionary<MessageDescriptor, byte> alreadySeen = new Dictionary<MessageDescriptor, byte>();
+ hasRequiredFields = CheckRequiredFields(alreadySeen);
+ }
+
+ private bool CheckRequiredFields(IDictionary<MessageDescriptor, byte> alreadySeen)
+ {
+ if (alreadySeen.ContainsKey(this))
+ {
+ // The type is already in the cache. This means that either:
+ // a. The type has no required fields.
+ // b. We are in the midst of checking if the type has required fields,
+ // somewhere up the stack. In this case, we know that if the type
+ // has any required fields, they'll be found when we return to it,
+ // and the whole call to HasRequiredFields() will return true.
+ // Therefore, we don't have to check if this type has required fields
+ // here.
+ return false;
+ }
+ alreadySeen[this] = 0; // Value is irrelevant; we want set semantics
+
+ // If the type allows extensions, an extension with message type could contain
+ // required fields, so we have to be conservative and assume such an
+ // extension exists.
+ if (Proto.ExtensionRangeCount != 0)
+ {
+ return true;
+ }
+
+ foreach (FieldDescriptor field in Fields)
+ {
+ if (field.IsRequired)
+ {
+ return true;
+ }
+ if (field.MappedType == MappedType.Message)
+ {
+ if (field.MessageType.CheckRequiredFields(alreadySeen))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// See FileDescriptor.ReplaceProto
+ /// </summary>
+ internal override void ReplaceProto(DescriptorProto newProto)
+ {
+ base.ReplaceProto(newProto);
+
+ for (int i = 0; i < nestedTypes.Count; i++)
+ {
+ nestedTypes[i].ReplaceProto(newProto.GetNestedType(i));
+ }
+
+ for (int i = 0; i < enumTypes.Count; i++)
+ {
+ enumTypes[i].ReplaceProto(newProto.GetEnumType(i));
+ }
+
+ for (int i = 0; i < fields.Count; i++)
+ {
+ fields[i].ReplaceProto(newProto.GetField(i));
+ }
+
+ for (int i = 0; i < extensions.Count; i++)
+ {
+ extensions[i].ReplaceProto(newProto.GetExtension(i));
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs b/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs index 45daecb7..f9ede245 100644 --- a/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs @@ -1,86 +1,94 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Describes a single method in a service. - /// </summary> - public sealed class MethodDescriptor : IndexedDescriptorBase<MethodDescriptorProto, MethodOptions> { - - private readonly ServiceDescriptor service; - private MessageDescriptor inputType; - private MessageDescriptor outputType; - - /// <value> - /// The service this method belongs to. - /// </value> - public ServiceDescriptor Service { - get { return service; } - } - - /// <value> - /// The method's input type. - /// </value> - public MessageDescriptor InputType { - get { return inputType; } - } - - /// <value> - /// The method's input type. - /// </value> - public MessageDescriptor OutputType { - get { return outputType; } - } - - internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file, - ServiceDescriptor parent, int index) - : base(proto, file, parent.FullName + "." + proto.Name, index) { - service = parent; - file.DescriptorPool.AddSymbol(this); - } - - internal void CrossLink() { - IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this); - if (!(lookup is MessageDescriptor)) { - throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type."); - } - inputType = (MessageDescriptor) lookup; - - lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this); - if (!(lookup is MessageDescriptor)) { - throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type."); - } - outputType = (MessageDescriptor) lookup; - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Describes a single method in a service.
+ /// </summary>
+ public sealed class MethodDescriptor : IndexedDescriptorBase<MethodDescriptorProto, MethodOptions>
+ {
+ private readonly ServiceDescriptor service;
+ private MessageDescriptor inputType;
+ private MessageDescriptor outputType;
+
+ /// <value>
+ /// The service this method belongs to.
+ /// </value>
+ public ServiceDescriptor Service
+ {
+ get { return service; }
+ }
+
+ /// <value>
+ /// The method's input type.
+ /// </value>
+ public MessageDescriptor InputType
+ {
+ get { return inputType; }
+ }
+
+ /// <value>
+ /// The method's input type.
+ /// </value>
+ public MessageDescriptor OutputType
+ {
+ get { return outputType; }
+ }
+
+ internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file,
+ ServiceDescriptor parent, int index)
+ : base(proto, file, parent.FullName + "." + proto.Name, index)
+ {
+ service = parent;
+ file.DescriptorPool.AddSymbol(this);
+ }
+
+ internal void CrossLink()
+ {
+ IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this);
+ if (!(lookup is MessageDescriptor))
+ {
+ throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type.");
+ }
+ inputType = (MessageDescriptor) lookup;
+
+ lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this);
+ if (!(lookup is MessageDescriptor))
+ {
+ throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type.");
+ }
+ outputType = (MessageDescriptor) lookup;
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs b/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs index 81798bfd..02549f9c 100644 --- a/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs @@ -1,67 +1,73 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -namespace Google.ProtocolBuffers.Descriptors { - /// <summary> - /// Represents a package in the symbol table. We use PackageDescriptors - /// just as placeholders so that someone cannot define, say, a message type - /// that has the same name as an existing package. - /// </summary> - internal sealed class PackageDescriptor : IDescriptor<IMessage> { - - private readonly string name; - private readonly string fullName; - private readonly FileDescriptor file; - - internal PackageDescriptor(string name, string fullName, FileDescriptor file) { - this.file = file; - this.fullName = fullName; - this.name = name; - } - - public IMessage Proto { - get { return file.Proto; } - } - - public string Name { - get { return name; } - } - - public string FullName { - get { return fullName; } - } - - public FileDescriptor File { - get { return file; } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Represents a package in the symbol table. We use PackageDescriptors
+ /// just as placeholders so that someone cannot define, say, a message type
+ /// that has the same name as an existing package.
+ /// </summary>
+ internal sealed class PackageDescriptor : IDescriptor<IMessage>
+ {
+ private readonly string name;
+ private readonly string fullName;
+ private readonly FileDescriptor file;
+
+ internal PackageDescriptor(string name, string fullName, FileDescriptor file)
+ {
+ this.file = file;
+ this.fullName = fullName;
+ this.name = name;
+ }
+
+ public IMessage Proto
+ {
+ get { return file.Proto; }
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public string FullName
+ {
+ get { return fullName; }
+ }
+
+ public FileDescriptor File
+ {
+ get { return file; }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs b/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs index 349b756d..417c0838 100644 --- a/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs +++ b/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs @@ -1,83 +1,89 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. -using System; -using System.Collections.Generic; -using Google.ProtocolBuffers.DescriptorProtos; - -namespace Google.ProtocolBuffers.Descriptors { - - /// <summary> - /// Describes a service type. - /// </summary> - public sealed class ServiceDescriptor : IndexedDescriptorBase<ServiceDescriptorProto, ServiceOptions> { - - private readonly IList<MethodDescriptor> methods; - - public ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index) - : base(proto, file, ComputeFullName(file, null, proto.Name), index) { - - methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.MethodList, - (method, i) => new MethodDescriptor(method, file, this, i)); - - file.DescriptorPool.AddSymbol(this); - } - - /// <value> - /// An unmodifiable list of methods in this service. - /// </value> - public IList<MethodDescriptor> Methods { - get { return methods; } - } - - /// <summary> - /// Finds a method by name. - /// </summary> - /// <param name="name">The unqualified name of the method (e.g. "Foo").</param> - /// <returns>The method's decsriptor, or null if not found.</returns> - public MethodDescriptor FindMethodByName(String name) { - return File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name); - } - - internal void CrossLink() { - foreach (MethodDescriptor method in methods) { - method.CrossLink(); - } - } - - internal override void ReplaceProto(ServiceDescriptorProto newProto) { - base.ReplaceProto(newProto); - for (int i = 0; i < methods.Count; i++) { - methods[i].ReplaceProto(newProto.GetMethod(i)); - } - } - } -} +// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// 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.
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.Descriptors
+{
+ /// <summary>
+ /// Describes a service type.
+ /// </summary>
+ public sealed class ServiceDescriptor : IndexedDescriptorBase<ServiceDescriptorProto, ServiceOptions>
+ {
+ private readonly IList<MethodDescriptor> methods;
+
+ public ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)
+ : base(proto, file, ComputeFullName(file, null, proto.Name), index)
+ {
+ methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.MethodList,
+ (method, i) => new MethodDescriptor(method, file, this, i));
+
+ file.DescriptorPool.AddSymbol(this);
+ }
+
+ /// <value>
+ /// An unmodifiable list of methods in this service.
+ /// </value>
+ public IList<MethodDescriptor> Methods
+ {
+ get { return methods; }
+ }
+
+ /// <summary>
+ /// Finds a method by name.
+ /// </summary>
+ /// <param name="name">The unqualified name of the method (e.g. "Foo").</param>
+ /// <returns>The method's decsriptor, or null if not found.</returns>
+ public MethodDescriptor FindMethodByName(String name)
+ {
+ return File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name);
+ }
+
+ internal void CrossLink()
+ {
+ foreach (MethodDescriptor method in methods)
+ {
+ method.CrossLink();
+ }
+ }
+
+ internal override void ReplaceProto(ServiceDescriptorProto newProto)
+ {
+ base.ReplaceProto(newProto);
+ for (int i = 0; i < methods.Count; i++)
+ {
+ methods[i].ReplaceProto(newProto.GetMethod(i));
+ }
+ }
+ }
+}
\ No newline at end of file |