Remove a lot of code which wasn't needed any more.

pull/544/head
Jon Skeet 10 years ago
parent e75a10d8ff
commit aa5104143c
  1. 5
      csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs
  2. 1
      csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  3. 60
      csharp/src/ProtocolBuffers.Test/WireFormatTest.cs
  4. 18
      csharp/src/ProtocolBuffers/ByteArray.cs
  5. 32
      csharp/src/ProtocolBuffers/ByteString.cs
  6. 122
      csharp/src/ProtocolBuffers/Collections/Dictionaries.cs
  7. 74
      csharp/src/ProtocolBuffers/Collections/Enumerables.cs
  8. 110
      csharp/src/ProtocolBuffers/Collections/Lists.cs
  9. 10
      csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
  10. 47
      csharp/src/ProtocolBuffers/Collections/RepeatedFieldExtensions.cs
  11. 4
      csharp/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs
  12. 186
      csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs
  13. 85
      csharp/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs
  14. 36
      csharp/src/ProtocolBuffers/Descriptors/FieldType.cs
  15. 65
      csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
  16. 52
      csharp/src/ProtocolBuffers/Descriptors/MappedType.cs
  17. 106
      csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs
  18. 7
      csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
  19. 7
      csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
  20. 159
      csharp/src/ProtocolBuffers/TextGenerator.cs
  21. 26
      csharp/src/ProtocolBuffers/ThrowHelper.cs
  22. 1
      csharp/src/ProtocolBuffers/WireFormat.cs

@ -147,17 +147,14 @@ namespace Google.Protobuf
Assert.AreEqual(messageType, primitiveField.ContainingType);
Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File);
Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
Assert.AreEqual(MappedType.Int32, primitiveField.MappedType);
Assert.IsNull(primitiveField.Options);
Assert.AreEqual("single_nested_enum", enumField.Name);
Assert.AreEqual(FieldType.Enum, enumField.FieldType);
Assert.AreEqual(MappedType.Enum, enumField.MappedType);
// Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType);
Assert.AreEqual("single_foreign_message", messageField.Name);
Assert.AreEqual(FieldType.Message, messageField.FieldType);
Assert.AreEqual(MappedType.Message, messageField.MappedType);
Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType);
}
@ -169,9 +166,7 @@ namespace Google.Protobuf
FieldDescriptor repeatedField =
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32");
Assert.IsFalse(singleField.IsRequired);
Assert.IsFalse(singleField.IsRepeated);
Assert.IsFalse(repeatedField.IsRequired);
Assert.IsTrue(repeatedField.IsRepeated);
}

@ -89,7 +89,6 @@
<Compile Include="IssuesTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestCornerCases.cs" />
<Compile Include="WireFormatTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">

@ -1,60 +0,0 @@
#region Copyright notice and license
// 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.
#endregion
using System.Reflection;
using Google.Protobuf.Descriptors;
using NUnit.Framework;
namespace Google.Protobuf
{
public class WireFormatTest
{
/// <summary>
/// Keeps the attributes on FieldType and the switch statement in WireFormat in sync.
/// </summary>
[Test]
public void FieldTypeToWireTypeMapping()
{
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];
Assert.AreEqual(mapping.WireType, WireFormat.GetWireType(fieldType));
}
}
}
}

@ -59,19 +59,11 @@ namespace Google.Protobuf
}
else
{
ByteCopy(src, srcOffset, dst, dstOffset, count);
}
}
/// <summary>
/// Copy the bytes provided with a for loop, faster when there are only a few bytes to copy
/// </summary>
internal static void ByteCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
{
int stop = srcOffset + count;
for (int i = srcOffset; i < stop; i++)
{
dst[dstOffset++] = src[i];
int stop = srcOffset + count;
for (int i = srcOffset; i < stop; i++)
{
dst[dstOffset++] = src[i];
}
}
}

@ -264,38 +264,6 @@ namespace Google.Protobuf
return true;
}
/// <summary>
/// Builder for ByteStrings which allows them to be created without extra
/// copying being involved. This has to be a nested type in order to have access
/// to the private ByteString constructor.
/// </summary>
internal sealed class CodedBuilder
{
private readonly CodedOutputStream output;
private readonly byte[] buffer;
internal CodedBuilder(int size)
{
buffer = new byte[size];
output = CodedOutputStream.CreateInstance(buffer);
}
internal ByteString Build()
{
output.CheckNoSpaceLeft();
// We can be confident that the CodedOutputStream will not modify the
// underlying bytes anymore because it already wrote all of them. So,
// no need to make a copy.
return new ByteString(buffer);
}
internal CodedOutputStream CodedOutput
{
get { return output; }
}
}
/// <summary>
/// Used internally by CodedOutputStream to avoid creating a copy for the write
/// </summary>

@ -1,122 +0,0 @@
// 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;
using System.Collections.Generic;
namespace Google.Protobuf.Collections
{
/// <summary>
/// Utility class for dictionaries.
/// </summary>
public static class Dictionaries
{
/// <summary>
/// Compares two dictionaries for equality. Each value is compared with equality using Equals
/// for non-IEnumerable implementations, and using EnumerableEquals otherwise.
/// TODO(jonskeet): This is clearly pretty slow, and involves lots of boxing/unboxing...
/// </summary>
public static bool Equals<TKey, TValue>(IDictionary<TKey, TValue> left, IDictionary<TKey, TValue> right)
{
if (left.Count != right.Count)
{
return false;
}
foreach (KeyValuePair<TKey, TValue> leftEntry in left)
{
TValue rightValue;
if (!right.TryGetValue(leftEntry.Key, out rightValue))
{
return false;
}
IEnumerable leftEnumerable = leftEntry.Value as IEnumerable;
IEnumerable rightEnumerable = rightValue as IEnumerable;
if (leftEnumerable == null || rightEnumerable == null)
{
if (!Equals(leftEntry.Value, rightValue))
{
return false;
}
}
else
{
if (!Enumerables.Equals(leftEnumerable, rightEnumerable))
{
return false;
}
}
}
return true;
}
public static IDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
{
return dictionary.IsReadOnly ? dictionary : new ReadOnlyDictionary<TKey, TValue>(dictionary);
}
/// <summary>
/// Creates a hashcode for a dictionary by XORing the hashcodes of all the fields
/// and values. (By XORing, we avoid ordering issues.)
/// TODO(jonskeet): Currently XORs other stuff too, and assumes non-null values.
/// </summary>
public static int GetHashCode<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
{
int ret = 31;
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
{
int hash = entry.Key.GetHashCode() ^ GetDeepHashCode(entry.Value);
ret ^= hash;
}
return ret;
}
/// <summary>
/// Determines the hash of a value by either taking it directly or hashing all the elements
/// for IEnumerable implementations.
/// </summary>
private static int GetDeepHashCode(object value)
{
IEnumerable iterable = value as IEnumerable;
if (iterable == null)
{
return value.GetHashCode();
}
int hash = 29;
foreach (object element in iterable)
{
hash = hash*37 + element.GetHashCode();
}
return hash;
}
}
}

@ -1,74 +0,0 @@
// 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;
namespace Google.Protobuf.Collections
{
/// <summary>
/// Utility class for IEnumerable (and potentially the generic version in the future).
/// </summary>
public static class Enumerables
{
public static bool Equals(IEnumerable left, IEnumerable right)
{
IEnumerator leftEnumerator = left.GetEnumerator();
try
{
foreach (object rightObject in right)
{
if (!leftEnumerator.MoveNext())
{
return false;
}
if (!Equals(leftEnumerator.Current, rightObject))
{
return false;
}
}
if (leftEnumerator.MoveNext())
{
return false;
}
}
finally
{
IDisposable leftEnumeratorDisposable = leftEnumerator as IDisposable;
if (leftEnumeratorDisposable != null)
{
leftEnumeratorDisposable.Dispose();
}
}
return true;
}
}
}

@ -1,110 +0,0 @@
// 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.Collections.ObjectModel;
namespace Google.Protobuf.Collections
{
/// <summary>
/// Utility non-generic class for calling into Lists{T} using type inference.
/// </summary>
public static class Lists
{
/// <summary>
/// Returns a read-only view of the specified list.
/// </summary>
public static IList<T> AsReadOnly<T>(IList<T> list)
{
return Lists<T>.AsReadOnly(list);
}
public static bool Equals<T>(IList<T> left, IList<T> right)
{
if (left == right)
{
return true;
}
if (left == null || right == null)
{
return false;
}
if (left.Count != right.Count)
{
return false;
}
IEqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < left.Count; i++)
{
if (!comparer.Equals(left[i], right[i]))
{
return false;
}
}
return true;
}
public static int GetHashCode<T>(IList<T> list)
{
int hash = 31;
foreach (T element in list)
{
hash = hash*29 + element.GetHashCode();
}
return hash;
}
}
/// <summary>
/// Utility class for dealing with lists.
/// </summary>
public static class Lists<T>
{
private static readonly ReadOnlyCollection<T> empty = new ReadOnlyCollection<T>(new T[0]);
/// <summary>
/// Returns an immutable empty list.
/// </summary>
public static ReadOnlyCollection<T> Empty
{
get { return empty; }
}
/// <summary>
/// Returns either the original reference if it's already read-only,
/// or a new ReadOnlyCollection wrapping the original list.
/// </summary>
public static IList<T> AsReadOnly(IList<T> list)
{
return list.IsReadOnly ? list : new ReadOnlyCollection<T>(list);
}
}
}

@ -298,6 +298,16 @@ namespace Google.Protobuf.Collections
}
}
internal uint CalculateSize(Func<T, int> sizeComputer)
{
int size = 0;
for (int i = 0; i < count; i++)
{
size += sizeComputer(array[i]);
}
return (uint)size;
}
public struct Enumerator : IEnumerator<T>
{
private int index;

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Google.Protobuf.Collections
{
public static class RepeatedFieldExtensions
{
internal static uint CalculateSize<T>(this RepeatedField<T> list, Func<T, int> sizeComputer)
{
int size = 0;
foreach (var item in list)
{
size += sizeComputer(item);
}
return (uint)size;
}
/*
/// <summary>
/// Calculates the serialized data size, including one tag per value.
/// </summary>
public static int CalculateTotalSize<T>(this RepeatedField<T> list, int tagSize, Func<T, int> sizeComputer)
{
if (list.Count == 0)
{
return 0;
}
return (int)(dataSize + tagSize * list.Count);
}
/// <summary>
/// Calculates the serialized data size, as a packed array (tag, length, data).
/// </summary>
public static int CalculateTotalPackedSize(int tagSize)
{
if (Count == 0)
{
return 0;
}
uint dataSize = CalculateSize();
return tagSize + CodedOutputStream.ComputeRawVarint32Size(dataSize) + (int)dataSize;
}
*/
}
}

@ -30,7 +30,7 @@
// (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.Protobuf.Collections;
using System.Collections.ObjectModel;
namespace Google.Protobuf.Descriptors
{
@ -58,7 +58,7 @@ namespace Google.Protobuf.Descriptors
{
array[i] = converter(input[i], i);
}
return Lists<TOutput>.AsReadOnly(array);
return new ReadOnlyCollection<TOutput>(array);
}
}
}

@ -43,24 +43,21 @@ namespace Google.Protobuf.Descriptors
public sealed class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>,
IComparable<FieldDescriptor>
{
private readonly MessageDescriptor extensionScope;
private EnumDescriptor enumType;
private MessageDescriptor messageType;
private MessageDescriptor containingType;
private OneofDescriptor containingOneof;
private FieldType fieldType;
private MappedType mappedType;
private readonly object optionsLock = new object();
internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
MessageDescriptor parent, int index, bool isExtension)
MessageDescriptor parent, int index)
: base(proto, file, ComputeFullName(file, parent, proto.Name), index)
{
if (proto.Type != 0)
{
fieldType = GetFieldTypeFromProtoType(proto.Type);
mappedType = FieldTypeToMappedTypeMap[fieldType];
}
if (FieldNumber <= 0)
@ -68,38 +65,16 @@ namespace Google.Protobuf.Descriptors
throw new DescriptorValidationException(this,
"Field numbers must be positive integers.");
}
if (isExtension)
containingType = parent;
if (proto.OneofIndex != 0)
{
if (proto.Extendee != "")
if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count)
{
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;
"FieldDescriptorProto.oneof_index is out of range for type " + parent.Name);
}
}
else
{
containingType = parent;
if (proto.OneofIndex != 0)
{
if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count)
{
throw new DescriptorValidationException(this,
"FieldDescriptorProto.oneof_index is out of range for type " + parent.Name);
}
containingOneof = parent.Oneofs[proto.OneofIndex];
containingOneof.fieldCount ++;
}
extensionScope = null;
containingOneof = parent.Oneofs[proto.OneofIndex];
containingOneof.fieldCount ++;
}
file.DescriptorPool.AddSymbol(this);
@ -151,51 +126,7 @@ namespace Google.Protobuf.Descriptors
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
{
@ -205,16 +136,7 @@ namespace Google.Protobuf.Descriptors
public bool IsPacked
{
get { return Proto.Options.Packed; }
}
/// <value>
/// Indicates whether or not this field is an extension. (Only relevant when parsing
/// the proto2 descriptor...)
/// </value>
internal bool IsExtension
{
get { return Proto.Extendee != ""; }
}
}
/// <summary>
/// Get the field's containing type. For extensions, this is the type being
@ -229,46 +151,7 @@ namespace Google.Protobuf.Descriptors
public OneofDescriptor ContainingOneof
{
get { return containingOneof; }
}
/// <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
{
@ -303,7 +186,7 @@ namespace Google.Protobuf.Descriptors
{
get
{
if (MappedType != MappedType.Enum)
if (fieldType != FieldType.Enum)
{
throw new InvalidOperationException("EnumType is only valid for enum fields.");
}
@ -318,7 +201,7 @@ namespace Google.Protobuf.Descriptors
{
get
{
if (MappedType != MappedType.Message)
if (fieldType != FieldType.Message)
{
throw new InvalidOperationException("MessageType is only valid for enum fields.");
}
@ -326,25 +209,6 @@ namespace Google.Protobuf.Descriptors
}
}
/// <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>
@ -361,12 +225,10 @@ namespace Google.Protobuf.Descriptors
if (typeDescriptor is MessageDescriptor)
{
fieldType = FieldType.Message;
mappedType = MappedType.Message;
}
else if (typeDescriptor is EnumDescriptor)
{
fieldType = FieldType.Enum;
mappedType = MappedType.Enum;
}
else
{
@ -374,7 +236,7 @@ namespace Google.Protobuf.Descriptors
}
}
if (MappedType == MappedType.Message)
if (fieldType == FieldType.Message)
{
if (!(typeDescriptor is MessageDescriptor))
{
@ -388,7 +250,7 @@ namespace Google.Protobuf.Descriptors
throw new DescriptorValidationException(this, "Messages can't have default values.");
}
}
else if (MappedType == Descriptors.MappedType.Enum)
else if (fieldType == FieldType.Enum)
{
if (!(typeDescriptor is EnumDescriptor))
{
@ -403,7 +265,7 @@ namespace Google.Protobuf.Descriptors
}
else
{
if (MappedType == MappedType.Message || MappedType == MappedType.Enum)
if (fieldType == FieldType.Message || fieldType == FieldType.Enum)
{
throw new DescriptorValidationException(this, "Field with message or enum type missing type_name.");
}
@ -411,25 +273,11 @@ namespace Google.Protobuf.Descriptors
// Note: no attempt to perform any default value parsing
if (!IsExtension)
{
File.DescriptorPool.AddFieldByNumber(this);
}
File.DescriptorPool.AddFieldByNumber(this);
if (containingType != null && containingType.Options != 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.");
}
throw new DescriptorValidationException(this, "MessageSet format is not supported.");
}
}
}

@ -1,85 +0,0 @@
// 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.Protobuf.Collections;
namespace Google.Protobuf.Descriptors
{
/// <summary>
/// Defined specifically for the <see cref="FieldType" /> enumeration,
/// this allows each field type to specify the mapped type and wire type.
/// </summary>
[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 (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;
}
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;
}
}
}

@ -38,23 +38,23 @@ namespace Google.Protobuf.Descriptors
/// </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
Double,
Float,
Int64,
UInt64,
Int32,
Fixed64,
Fixed32,
Bool,
String,
Group,
Message,
Bytes,
UInt32,
SFixed32,
SFixed64,
SInt32,
SInt64,
Enum
}
}

@ -45,11 +45,10 @@ namespace Google.Protobuf.Descriptors
/// </summary>
public sealed class FileDescriptor : IDescriptor<FileDescriptorProto>
{
private FileDescriptorProto proto;
private readonly 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 IList<FileDescriptor> publicDependencies;
private readonly DescriptorPool pool;
@ -86,10 +85,6 @@ namespace Google.Protobuf.Descriptors
services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service,
(service, index) =>
new ServiceDescriptor(service, this, index));
extensions = DescriptorUtil.ConvertAndMakeReadOnly(proto.Extension,
(field, index) =>
new FieldDescriptor(field, this, null, index, true));
}
/// <summary>
@ -129,9 +124,6 @@ namespace Google.Protobuf.Descriptors
return new ReadOnlyCollection<FileDescriptor>(publicDependencies);
}
static readonly char[] PathSeperators = new char[] { '/', '\\' };
/// <value>
/// The descriptor in its protocol message representation.
/// </value>
@ -189,14 +181,6 @@ namespace Google.Protobuf.Descriptors
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>
@ -350,16 +334,6 @@ namespace Google.Protobuf.Descriptors
{
service.CrossLink();
}
foreach (FieldDescriptor extension in extensions)
{
extension.CrossLink();
}
foreach (MessageDescriptor message in messageTypes)
{
message.CheckRequiredFields();
}
}
/// <summary>
@ -415,42 +389,7 @@ namespace Google.Protobuf.Descriptors
descriptorAssigner(result);
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.MessageType[i]);
}
for (int i = 0; i < enumTypes.Count; i++)
{
enumTypes[i].ReplaceProto(proto.EnumType[i]);
}
for (int i = 0; i < services.Count; i++)
{
services[i].ReplaceProto(proto.Service[i]);
}
for (int i = 0; i < extensions.Count; i++)
{
extensions[i].ReplaceProto(proto.Extension[i]);
}
}
public override string ToString()
{
return "FileDescriptor for " + proto.Name;

@ -1,52 +0,0 @@
// 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.Protobuf.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
}
}

@ -44,10 +44,8 @@ namespace Google.Protobuf.Descriptors
private readonly IList<MessageDescriptor> nestedTypes;
private readonly IList<EnumDescriptor> enumTypes;
private readonly IList<FieldDescriptor> fields;
private readonly IList<FieldDescriptor> extensions;
private readonly IList<OneofDescriptor> oneofs;
private bool hasRequiredFields;
internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex)
: base(proto, file, ComputeFullName(file, parent, proto.Name), typeIndex)
{
@ -68,11 +66,7 @@ namespace Google.Protobuf.Descriptors
// TODO(jonskeet): Sort fields first?
fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field,
(field, index) =>
new FieldDescriptor(field, file, this, index, false));
extensions = DescriptorUtil.ConvertAndMakeReadOnly(proto.Extension,
(field, index) =>
new FieldDescriptor(field, file, this, index, true));
new FieldDescriptor(field, file, this, index));
for (int i = 0; i < proto.OneofDecl.Count; i++)
{
@ -106,14 +100,6 @@ namespace Google.Protobuf.Descriptors
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>
@ -135,32 +121,6 @@ namespace Google.Protobuf.Descriptors
get { return oneofs; }
}
/// <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.ExtensionRange)
{
if (range.Start <= number && number < range.End)
{
return true;
}
}
return false;
}
/// <summary>
/// Finds a field by field name.
/// </summary>
@ -194,7 +154,7 @@ namespace Google.Protobuf.Descriptors
}
/// <summary>
/// Looks up and cross-links all fields, nested types, and extensions.
/// Looks up and cross-links all fields and nested types.
/// </summary>
internal void CrossLink()
{
@ -208,62 +168,11 @@ namespace Google.Protobuf.Descriptors
field.CrossLink();
}
foreach (FieldDescriptor extension in extensions)
{
extension.CrossLink();
}
foreach (OneofDescriptor oneof in oneofs)
{
// oneof.C
}
}
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.ExtensionRange.Count != 0)
{
return true;
// TODO(jonskeet): Do we need to do this?
// oneof.C
}
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>
@ -287,11 +196,6 @@ namespace Google.Protobuf.Descriptors
{
fields[i].ReplaceProto(newProto.Field[i]);
}
for (int i = 0; i < extensions.Count; i++)
{
extensions[i].ReplaceProto(newProto.Extension[i]);
}
}
}
}

@ -69,7 +69,6 @@ namespace Google.Protobuf.FieldAccess
get
{
FieldDescriptor field = descriptor.FindFieldByNumber(fieldNumber);
// TODO: Handle extensions.
return accessors[field.Index];
}
}
@ -82,12 +81,6 @@ namespace Google.Protobuf.FieldAccess
{
throw new ArgumentException("FieldDescriptor does not match message type.");
}
else if (field.IsExtension)
{
// If this type had extensions, it would subclass ExtendableMessage,
// which overrides the reflection interface to handle extensions.
throw new ArgumentException("This type does not have extensions.");
}
return accessors[field.Index];
}
}

@ -54,16 +54,12 @@
<ItemGroup>
<Compile Include="ByteArray.cs" />
<Compile Include="ByteString.cs" />
<Compile Include="Collections\Enumerables.cs" />
<Compile Include="CodedOutputStream.ComputeSize.cs" />
<Compile Include="CodedInputStream.cs" />
<Compile Include="CodedOutputStream.cs" />
<Compile Include="Collections\Dictionaries.cs" />
<Compile Include="Collections\Lists.cs" />
<Compile Include="Collections\MapField.cs" />
<Compile Include="Collections\ReadOnlyDictionary.cs" />
<Compile Include="Collections\RepeatedField.cs" />
<Compile Include="Collections\RepeatedFieldExtensions.cs" />
<Compile Include="DescriptorProtos\DescriptorProtoFile.cs" />
<Compile Include="DescriptorProtos\IDescriptorProto.cs" />
<Compile Include="DescriptorProtos\PartialClasses.cs" />
@ -74,13 +70,11 @@
<Compile Include="Descriptors\EnumDescriptor.cs" />
<Compile Include="Descriptors\EnumValueDescriptor.cs" />
<Compile Include="Descriptors\FieldDescriptor.cs" />
<Compile Include="Descriptors\FieldMappingAttribute.cs" />
<Compile Include="Descriptors\FieldType.cs" />
<Compile Include="Descriptors\FileDescriptor.cs" />
<Compile Include="Descriptors\OneofDescriptor.cs" />
<Compile Include="Descriptors\IDescriptor.cs" />
<Compile Include="Descriptors\IndexedDescriptorBase.cs" />
<Compile Include="Descriptors\MappedType.cs" />
<Compile Include="Descriptors\MessageDescriptor.cs" />
<Compile Include="Descriptors\MethodDescriptor.cs" />
<Compile Include="Descriptors\PackageDescriptor.cs" />
@ -101,7 +95,6 @@
<Compile Include="LimitedInputStream.cs" />
<Compile Include="MessageParser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TextGenerator.cs" />
<Compile Include="ThrowHelper.cs" />
<Compile Include="WireFormat.cs" />
</ItemGroup>

@ -1,159 +0,0 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.IO;
using System.Text;
namespace Google.Protobuf
{
/// <summary>
/// Helper class to control indentation. Used for TextFormat and by ProtoGen.
/// </summary>
public sealed class TextGenerator
{
/// <summary>
/// The string to use at the end of each line. We assume that "Print" is only called using \n
/// to indicate a line break; that's what we use to detect when we need to indent etc, and
/// *just* the \n is replaced with the contents of lineBreak.
/// </summary>
private readonly string lineBreak;
/// <summary>
/// Writer to write formatted text to.
/// </summary>
private readonly TextWriter writer;
/// <summary>
/// Keeps track of whether the next piece of text should be indented
/// </summary>
private bool atStartOfLine = true;
/// <summary>
/// Keeps track of the current level of indentation
/// </summary>
private readonly StringBuilder indent = new StringBuilder();
/// <summary>
/// Creates a generator writing to the given writer. The writer
/// is not closed by this class.
/// </summary>
public TextGenerator(TextWriter writer, string lineBreak)
{
this.writer = writer;
this.lineBreak = lineBreak;
}
/// <summary>
/// Indents text by two spaces. After calling Indent(), two spaces
/// will be inserted at the beginning of each line of text. Indent() may
/// be called multiple times to produce deeper indents.
/// </summary>
public void Indent()
{
indent.Append(" ");
}
/// <summary>
/// Reduces the current indent level by two spaces.
/// </summary>
public void Outdent()
{
if (indent.Length == 0)
{
throw new InvalidOperationException("Too many calls to Outdent()");
}
indent.Length -= 2;
}
public void WriteLine(string text)
{
Print(text);
Print("\n");
}
public void WriteLine(string format, params object[] args)
{
WriteLine(string.Format(format, args));
}
public void WriteLine()
{
WriteLine("");
}
/// <summary>
/// Prints the given text to the output stream, indenting at line boundaries.
/// </summary>
/// <param name="text"></param>
public void Print(string text)
{
int pos = 0;
for (int i = 0; i < text.Length; i++)
{
if (text[i] == '\n')
{
// Strip off the \n from what we write
Write(text.Substring(pos, i - pos));
Write(lineBreak);
pos = i + 1;
atStartOfLine = true;
}
}
Write(text.Substring(pos));
}
public void Write(string format, params object[] args)
{
Write(string.Format(format, args));
}
private void Write(string data)
{
if (data.Length == 0)
{
return;
}
if (atStartOfLine)
{
atStartOfLine = false;
writer.Write(indent);
}
writer.Write(data);
}
}
}

@ -35,7 +35,6 @@
#endregion
using System;
using System.Collections.Generic;
namespace Google.Protobuf
{
@ -54,30 +53,5 @@ namespace Google.Protobuf
throw new ArgumentNullException(name);
}
}
/// <summary>
/// Throws an ArgumentNullException if the given value is null.
/// </summary>
internal static void ThrowIfNull(object value)
{
if (value == null)
{
throw new ArgumentNullException();
}
}
/// <summary>
/// Throws an ArgumentNullException if the given value or any element within it is null.
/// </summary>
internal static void ThrowIfAnyNull<T>(IEnumerable<T> sequence)
{
foreach (T t in sequence)
{
if (t == null)
{
throw new ArgumentNullException();
}
}
}
}
}

@ -114,7 +114,6 @@ namespace Google.Protobuf
/// <summary>
/// Makes a tag value given a field number and wire type.
/// TODO(jonskeet): Should we just have a Tag structure?
/// </summary>
public static uint MakeTag(int fieldNumber, WireType wireType)
{

Loading…
Cancel
Save