From 6f300442bc0e5eced5f48820bcd5f24fce9e3867 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Thu, 6 Aug 2015 14:29:34 +0100 Subject: [PATCH] Tidying up - fix a bunch of TODOs and remove outdated ones. --- .../CodedInputStreamTest.cs | 1 - csharp/src/Google.Protobuf/ByteString.cs | 3 -- .../src/Google.Protobuf/CodedInputStream.cs | 25 +++++++------- .../src/Google.Protobuf/CodedOutputStream.cs | 22 +++++++----- .../Collections/RepeatedField.cs | 6 ++-- .../Google.Protobuf/FrameworkPortability.cs | 3 +- csharp/src/Google.Protobuf/IMessage.cs | 2 -- csharp/src/Google.Protobuf/JsonFormatter.cs | 3 +- .../Reflection/FieldAccessorBase.cs | 10 +++--- .../Reflection/FileDescriptor.cs | 34 +++++++++---------- .../Reflection/IFieldAccessor.cs | 8 ++--- .../Reflection/MapFieldAccessor.cs | 4 +-- .../Reflection/OneofAccessor.cs | 12 +++---- .../Reflection/ReflectionUtil.cs | 24 ++++++------- .../Reflection/RepeatedFieldAccessor.cs | 4 +-- .../Reflection/SingleFieldAccessor.cs | 12 +++---- csharp/src/Google.Protobuf/WireFormat.cs | 13 ------- 17 files changed, 84 insertions(+), 102 deletions(-) diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs index 42c740ac4e..c8326d801b 100644 --- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs @@ -281,7 +281,6 @@ namespace Google.Protobuf CodedInputStream input = new CodedInputStream(ms); Assert.AreEqual(tag, input.ReadTag()); - // TODO(jonskeet): Should this be ArgumentNullException instead? Assert.Throws(() => input.ReadBytes()); } diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index 2aa62483f9..3d55f02da9 100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -40,7 +40,6 @@ namespace Google.Protobuf { /// /// Immutable array of bytes. - /// TODO(jonskeet): Implement the common collection interfaces? /// public sealed class ByteString : IEnumerable, IEquatable { @@ -284,8 +283,6 @@ namespace Google.Protobuf return !(lhs == rhs); } - // TODO(jonskeet): CopyTo if it turns out to be required - /// /// Compares this byte string with another object. /// diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs index dcd19e48ee..c8b33b33ba 100644 --- a/csharp/src/Google.Protobuf/CodedInputStream.cs +++ b/csharp/src/Google.Protobuf/CodedInputStream.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using System; using System.Collections.Generic; using System.IO; @@ -40,20 +41,21 @@ namespace Google.Protobuf /// Readings and decodes protocol message fields. /// /// - /// This class contains two kinds of methods: methods that read specific - /// protocol message constructs and field types (e.g. ReadTag and - /// ReadInt32) and methods that read low-level values (e.g. - /// ReadRawVarint32 and ReadRawBytes). If you are reading encoded protocol - /// messages, you should use the former methods, but if you are reading some - /// other format of your own design, use the latter. The names of the former - /// methods are taken from the protocol buffer type names, not .NET types. - /// (Hence ReadFloat instead of ReadSingle, and ReadBool instead of ReadBoolean.) - /// - /// TODO(jonskeet): Consider whether recursion and size limits shouldn't be readonly, - /// set at construction time. + /// + /// This class is generally used by generated code to read appropriate + /// primitives from the stream. It effectively encapsulates the lowest + /// levels of protocol buffer format. + /// + /// + /// Repeated fields and map fields are not handled by this class; use + /// and to serialize such fields. + /// /// public sealed class CodedInputStream { + // TODO(jonskeet): Consider whether recursion and size limits shouldn't be readonly, + // set at construction time. + /// /// Buffer of data read from the stream or provided at construction time. /// @@ -1022,7 +1024,6 @@ namespace Google.Protobuf if (totalBytesRetired + bufferPos + size > currentLimit) { // Read to the end of the stream (up to the current limit) anyway. - // TODO(jonskeet): This is the only usage of SkipRawBytes. Do we really need to do it? SkipRawBytes(currentLimit - totalBytesRetired - bufferPos); // Then fail. throw InvalidProtocolBufferException.TruncatedMessage(); diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs index 08ea7005a6..7f41cb7a62 100644 --- a/csharp/src/Google.Protobuf/CodedOutputStream.cs +++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using System; using System.IO; using System.Text; @@ -40,14 +41,19 @@ namespace Google.Protobuf /// Encodes and writes protocol message fields. /// /// - /// This class contains two kinds of methods: methods that write specific - /// protocol message constructs and field types (e.g. WriteTag and - /// WriteInt32) and methods that write low-level values (e.g. - /// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol - /// messages, you should use the former methods, but if you are writing some - /// other format of your own design, use the latter. The names of the former - /// methods are taken from the protocol buffer type names, not .NET types. - /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.) + /// + /// This class is generally used by generated code to write appropriate + /// primitives to the stream. It effectively encapsulates the lowest + /// levels of protocol buffer format. Unlike some other implementations, + /// this does not include combined "write tag and value" methods. Generated + /// code knows the exact byte representations of the tags they're going to write, + /// so there's no need to re-encode them each time. Manually-written code calling + /// this class should just call one of the WriteTag overloads before each value. + /// + /// + /// Repeated fields and map fields are not handled by this class; use + /// and to serialize such fields. + /// /// public sealed partial class CodedOutputStream { diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index c901864ad3..d9ced6ec53 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -88,7 +88,7 @@ namespace Google.Protobuf.Collections public void AddEntriesFrom(CodedInputStream input, FieldCodec codec) { // TODO: Inline some of the Add code, so we can avoid checking the size on every - // iteration and the mutability. + // iteration. uint tag = input.LastTag; var reader = codec.ValueReader; // Value types can be packed or not. @@ -315,7 +315,7 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("values"); } - // TODO: Check for ICollection and get the Count? + // TODO: Check for ICollection and get the Count, to optimize? foreach (T item in values) { Add(item); @@ -394,7 +394,6 @@ namespace Google.Protobuf.Collections { return false; } - // TODO(jonskeet): Does this box for enums? EqualityComparer comparer = EqualityComparer.Default; for (int i = 0; i < count; i++) { @@ -418,7 +417,6 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("item"); } - // TODO(jonskeet): Does this box for enums? EqualityComparer comparer = EqualityComparer.Default; for (int i = 0; i < count; i++) { diff --git a/csharp/src/Google.Protobuf/FrameworkPortability.cs b/csharp/src/Google.Protobuf/FrameworkPortability.cs index 082eb2e155..9498dbe4cc 100644 --- a/csharp/src/Google.Protobuf/FrameworkPortability.cs +++ b/csharp/src/Google.Protobuf/FrameworkPortability.cs @@ -40,10 +40,9 @@ namespace Google.Protobuf /// internal static class FrameworkPortability { - // TODO(jtattermusch): is this still a thing? // The value of RegexOptions.Compiled is 8. We can test for the presence at // execution time using Enum.IsDefined, so a single build will do the right thing - // on each platform. + // on each platform. (RegexOptions.Compiled isn't supported by PCLs.) internal static readonly RegexOptions CompiledRegexWhereAvailable = Enum.IsDefined(typeof(RegexOptions), 8) ? (RegexOptions)8 : RegexOptions.None; } diff --git a/csharp/src/Google.Protobuf/IMessage.cs b/csharp/src/Google.Protobuf/IMessage.cs index 147c83ca01..773845ff87 100644 --- a/csharp/src/Google.Protobuf/IMessage.cs +++ b/csharp/src/Google.Protobuf/IMessage.cs @@ -35,8 +35,6 @@ using Google.Protobuf.Reflection; namespace Google.Protobuf { - - // TODO(jonskeet): Do we want a "weak" (non-generic) version of IReflectedMessage? // TODO(jonskeet): Split these interfaces into separate files when we're happy with them. /// diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 7c4894beb9..12bbdfdde9 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -158,7 +158,6 @@ namespace Google.Protobuf { var accessor = field.Accessor; // Oneofs are written later - // TODO: Change to write out fields in order, interleaving oneofs appropriately (as per binary format) if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field) { continue; @@ -425,7 +424,7 @@ namespace Google.Protobuf if (descriptor.FullName == ListValue.Descriptor.FullName) { var fieldAccessor = descriptor.Fields[ListValue.ValuesFieldNumber].Accessor; - WriteList(builder, fieldAccessor, (IList) fieldAccessor.GetValue(value)); + WriteList(builder, fieldAccessor, (IList) fieldAccessor.GetValue((IMessage) value)); return; } if (descriptor.FullName == Value.Descriptor.FullName) diff --git a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs index 3fccf88408..82ce50518d 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs @@ -41,23 +41,23 @@ namespace Google.Protobuf.Reflection /// internal abstract class FieldAccessorBase : IFieldAccessor { - private readonly Func getValueDelegate; + private readonly Func getValueDelegate; private readonly FieldDescriptor descriptor; internal FieldAccessorBase(PropertyInfo property, FieldDescriptor descriptor) { this.descriptor = descriptor; - getValueDelegate = ReflectionUtil.CreateFuncObjectObject(property.GetGetMethod()); + getValueDelegate = ReflectionUtil.CreateFuncIMessageObject(property.GetGetMethod()); } public FieldDescriptor Descriptor { get { return descriptor; } } - public object GetValue(object message) + public object GetValue(IMessage message) { return getValueDelegate(message); } - public abstract void Clear(object message); - public abstract void SetValue(object message, object value); + public abstract void Clear(IMessage message); + public abstract void SetValue(IMessage message, object value); } } diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs index 7292770243..500e467c8a 100644 --- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs @@ -287,23 +287,23 @@ namespace Google.Protobuf.Reflection DescriptorPool pool = new DescriptorPool(dependencies); FileDescriptor result = new FileDescriptor(descriptorData, proto, dependencies, pool, allowUnknownDependencies, generatedCodeInfo); - // TODO(jonskeet): Reinstate these checks, or get rid of them entirely. They aren't in the Java code, - // and fail for the CustomOptions test right now. (We get "descriptor.proto" vs "google/protobuf/descriptor.proto".) - //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."); - // } - //} + // Validate that the dependencies we've been passed (as FileDescriptors) are actually the ones we + // need. + if (dependencies.Length != proto.Dependency.Count) + { + throw new DescriptorValidationException(result, + "Dependencies passed to FileDescriptor.BuildFrom() don't match " + + "those listed in the FileDescriptorProto."); + } + for (int i = 0; i < proto.Dependency.Count; i++) + { + if (dependencies[i].Name != proto.Dependency[i]) + { + throw new DescriptorValidationException(result, + "Dependencies passed to FileDescriptor.BuildFrom() don't match " + + "those listed in the FileDescriptorProto."); + } + } result.CrossLink(); return result; diff --git a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs index f97d73ee4e..c9e28f506a 100644 --- a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs @@ -45,20 +45,20 @@ namespace Google.Protobuf.Reflection /// FieldDescriptor Descriptor { get; } - // TODO: Should the argument type for these messages be IReflectedMessage? + // TODO: Should the argument type for these messages be IMessage? /// /// Clears the field in the specified message. (For repeated fields, /// this clears the list.) /// - void Clear(object message); + void Clear(IMessage message); /// /// Fetches the field value. For repeated values, this will be an /// implementation. For map values, this will be an /// implementation. /// - object GetValue(object message); + object GetValue(IMessage message); /// /// Mutator for single "simple" fields only. @@ -68,6 +68,6 @@ namespace Google.Protobuf.Reflection /// Map fields are mutated by fetching the value and manipulating it as a dictionary. /// /// The field is not a "simple" field. - void SetValue(object message, object value); + void SetValue(IMessage message, object value); } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs index 6df4c5f056..9ed7f8c4df 100644 --- a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs @@ -45,13 +45,13 @@ namespace Google.Protobuf.Reflection { } - public override void Clear(object message) + public override void Clear(IMessage message) { IDictionary list = (IDictionary) GetValue(message); list.Clear(); } - public override void SetValue(object message, object value) + public override void SetValue(IMessage message, object value) { throw new InvalidOperationException("SetValue is not implemented for map fields"); } diff --git a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs index ff51291b30..8714ab18ef 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs @@ -41,8 +41,8 @@ namespace Google.Protobuf.Reflection /// public sealed class OneofAccessor { - private readonly Func caseDelegate; - private readonly Action clearDelegate; + private readonly Func caseDelegate; + private readonly Action clearDelegate; private OneofDescriptor descriptor; internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor) @@ -52,10 +52,10 @@ namespace Google.Protobuf.Reflection throw new ArgumentException("Cannot read from property"); } this.descriptor = descriptor; - caseDelegate = ReflectionUtil.CreateFuncObjectT(caseProperty.GetGetMethod()); + caseDelegate = ReflectionUtil.CreateFuncIMessageT(caseProperty.GetGetMethod()); this.descriptor = descriptor; - clearDelegate = ReflectionUtil.CreateActionObject(clearMethod); + clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); } /// @@ -69,7 +69,7 @@ namespace Google.Protobuf.Reflection /// /// Clears the oneof in the specified message. /// - public void Clear(object message) + public void Clear(IMessage message) { clearDelegate(message); } @@ -77,7 +77,7 @@ namespace Google.Protobuf.Reflection /// /// Indicates which field in the oneof is set for specified message /// - public FieldDescriptor GetCaseFieldDescriptor(object message) + public FieldDescriptor GetCaseFieldDescriptor(IMessage message) { int fieldNumber = caseDelegate(message); if (fieldNumber > 0) diff --git a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs index 5b3cbb36f7..df820ca36b 100644 --- a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs +++ b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs @@ -56,52 +56,52 @@ namespace Google.Protobuf.Reflection /// Creates a delegate which will cast the argument to the appropriate method target type, /// call the method on it, then convert the result to object. /// - internal static Func CreateFuncObjectObject(MethodInfo method) + internal static Func CreateFuncIMessageObject(MethodInfo method) { - ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); + ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p"); Expression downcast = Expression.Convert(parameter, method.DeclaringType); Expression call = Expression.Call(downcast, method); Expression upcast = Expression.Convert(call, typeof(object)); - return Expression.Lambda>(upcast, parameter).Compile(); + return Expression.Lambda>(upcast, parameter).Compile(); } /// /// Creates a delegate which will cast the argument to the appropriate method target type, /// call the method on it, then convert the result to the specified type. /// - internal static Func CreateFuncObjectT(MethodInfo method) + internal static Func CreateFuncIMessageT(MethodInfo method) { - ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); + ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p"); Expression downcast = Expression.Convert(parameter, method.DeclaringType); Expression call = Expression.Call(downcast, method); Expression upcast = Expression.Convert(call, typeof(T)); - return Expression.Lambda>(upcast, parameter).Compile(); + return Expression.Lambda>(upcast, parameter).Compile(); } /// /// Creates a delegate which will execute the given method after casting the first argument to /// the target type of the method, and the second argument to the first parameter type of the method. /// - internal static Action CreateActionObjectObject(MethodInfo method) + internal static Action CreateActionIMessageObject(MethodInfo method) { - ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); + ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target"); ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg"); Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType); Expression call = Expression.Call(castTarget, method, castArgument); - return Expression.Lambda>(call, targetParameter, argParameter).Compile(); + return Expression.Lambda>(call, targetParameter, argParameter).Compile(); } /// /// Creates a delegate which will execute the given method after casting the first argument to /// the target type of the method. /// - internal static Action CreateActionObject(MethodInfo method) + internal static Action CreateActionIMessage(MethodInfo method) { - ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); + ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target"); Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); Expression call = Expression.Call(castTarget, method); - return Expression.Lambda>(call, targetParameter).Compile(); + return Expression.Lambda>(call, targetParameter).Compile(); } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs index acb3c8d5f1..bd40847092 100644 --- a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs @@ -45,13 +45,13 @@ namespace Google.Protobuf.Reflection { } - public override void Clear(object message) + public override void Clear(IMessage message) { IList list = (IList) GetValue(message); list.Clear(); } - public override void SetValue(object message, object value) + public override void SetValue(IMessage message, object value) { throw new InvalidOperationException("SetValue is not implemented for repeated fields"); } diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs index 851efc26da..de92fbc1a4 100644 --- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs @@ -46,8 +46,8 @@ namespace Google.Protobuf.Reflection // and proto2 vs proto3 for non-message types, as proto3 doesn't support "full" presence detection or default // values. - private readonly Action setValueDelegate; - private readonly Action clearDelegate; + private readonly Action setValueDelegate; + private readonly Action clearDelegate; internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { @@ -55,12 +55,10 @@ namespace Google.Protobuf.Reflection { throw new ArgumentException("Not all required properties/methods available"); } - setValueDelegate = ReflectionUtil.CreateActionObjectObject(property.GetSetMethod()); + setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); var clrType = property.PropertyType; - // TODO: What should clear on a oneof member do? Clear the oneof? - // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) object defaultValue = typeof(IMessage).IsAssignableFrom(clrType) ? null @@ -70,12 +68,12 @@ namespace Google.Protobuf.Reflection clearDelegate = message => SetValue(message, defaultValue); } - public override void Clear(object message) + public override void Clear(IMessage message) { clearDelegate(message); } - public override void SetValue(object message, object value) + public override void SetValue(IMessage message, object value) { setValueDelegate(message, value); } diff --git a/csharp/src/Google.Protobuf/WireFormat.cs b/csharp/src/Google.Protobuf/WireFormat.cs index b0e4a41f0f..faf1e715ef 100644 --- a/csharp/src/Google.Protobuf/WireFormat.cs +++ b/csharp/src/Google.Protobuf/WireFormat.cs @@ -43,19 +43,6 @@ namespace Google.Protobuf /// public static class WireFormat { - #region Fixed sizes. - - // TODO(jonskeet): Move these somewhere else. They're messy. Consider making FieldType a smarter kind of enum - internal const int Fixed32Size = 4; - internal const int Fixed64Size = 8; - internal const int SFixed32Size = 4; - internal const int SFixed64Size = 8; - internal const int FloatSize = 4; - internal const int DoubleSize = 8; - internal const int BoolSize = 1; - - #endregion - /// /// Wire types within protobuf encoding. ///