diff options
Diffstat (limited to 'src/ProtocolBuffers')
70 files changed, 16959 insertions, 0 deletions
diff --git a/src/ProtocolBuffers/AbstractBuilder.cs b/src/ProtocolBuffers/AbstractBuilder.cs new file mode 100644 index 00000000..11a82974 --- /dev/null +++ b/src/ProtocolBuffers/AbstractBuilder.cs @@ -0,0 +1,222 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Implementation of the non-generic IMessage interface as far as possible. + /// </summary> + public abstract class AbstractBuilder<TMessage, TBuilder> : IBuilder<TMessage, TBuilder> + where TMessage : AbstractMessage<TMessage, TBuilder> + where TBuilder : AbstractBuilder<TMessage, TBuilder> { + + protected abstract TBuilder ThisBuilder { get; } + + #region Unimplemented members of IBuilder + public abstract UnknownFieldSet UnknownFields { get; set; } + public abstract TBuilder MergeFrom(TMessage other); + public abstract bool IsInitialized { get; } + public abstract IDictionary<FieldDescriptor, object> AllFields { get; } + public abstract object this[FieldDescriptor field] { get; set; } + public abstract MessageDescriptor DescriptorForType { get; } + public abstract int GetRepeatedFieldCount(FieldDescriptor field); + public abstract object this[FieldDescriptor field, int index] { get; set; } + public abstract bool HasField(FieldDescriptor field); + public abstract TMessage Build(); + public abstract TMessage BuildPartial(); + public abstract TBuilder Clone(); + public abstract TMessage DefaultInstanceForType { get; } + public abstract IBuilder CreateBuilderForField(FieldDescriptor field); + public abstract TBuilder ClearField(FieldDescriptor field); + public abstract TBuilder AddRepeatedField(FieldDescriptor field, object value); + #endregion + + #region Implementation of methods which don't require type parameter information + public IMessage WeakBuild() { + return Build(); + } + + public IBuilder WeakAddRepeatedField(FieldDescriptor field, object value) { + return AddRepeatedField(field, value); + } + + public IBuilder WeakClear() { + return Clear(); + } + + public IBuilder WeakMergeFrom(IMessage message) { + return MergeFrom(message); + } + + public IBuilder WeakMergeFrom(CodedInputStream input) { + return MergeFrom(input); + } + + public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) { + return MergeFrom(input, registry); + } + + public IBuilder WeakMergeFrom(ByteString data) { + return MergeFrom(data); + } + + public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry) { + return MergeFrom(data, registry); + } + + public IMessage WeakBuildPartial() { + return BuildPartial(); + } + + public IBuilder WeakClone() { + return Clone(); + } + + public IMessage WeakDefaultInstanceForType { + get { return DefaultInstanceForType; } + } + + public IBuilder WeakClearField(FieldDescriptor field) { + return ClearField(field); + } + #endregion + + public TBuilder SetUnknownFields(UnknownFieldSet fields) { + UnknownFields = fields; + return ThisBuilder; + } + + public virtual TBuilder Clear() { + foreach(FieldDescriptor field in AllFields.Keys) { + ClearField(field); + } + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(IMessage other) { + if (other.DescriptorForType != DescriptorForType) { + throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type."); + } + + // Note: We don't attempt to verify that other's fields have valid + // types. Doing so would be a losing battle. We'd have to verify + // all sub-messages as well, and we'd have to make copies of all of + // them to insure that they don't change after verification (since + // the Message interface itself cannot enforce immutability of + // implementations). + // TODO(jonskeet): Provide a function somewhere called MakeDeepCopy() + // which allows people to make secure deep copies of messages. + foreach (KeyValuePair<FieldDescriptor, object> entry in other.AllFields) { + FieldDescriptor field = entry.Key; + if (field.IsRepeated) { + // Concatenate repeated fields + foreach (object element in (IEnumerable) entry.Value) { + AddRepeatedField(field, element); + } + } else if (field.MappedType == MappedType.Message) { + // Merge singular messages + IMessage existingValue = (IMessage) this[field]; + if (existingValue == existingValue.WeakDefaultInstanceForType) { + this[field] = entry.Value; + } else { + this[field] = existingValue.WeakCreateBuilderForType() + .WeakMergeFrom(existingValue) + .WeakMergeFrom((IMessage) entry.Value) + .WeakBuild(); + } + } else { + // Overwrite simple values + this[field] = entry.Value; + } + } + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(CodedInputStream input) { + return MergeFrom(input, ExtensionRegistry.Empty); + } + + public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) { + UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields); + unknownFields.MergeFrom(input, extensionRegistry, this); + UnknownFields = unknownFields.Build(); + return ThisBuilder; + } + + public virtual TBuilder MergeUnknownFields(UnknownFieldSet unknownFields) { + UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields) + .MergeFrom(unknownFields) + .Build(); + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(ByteString data) { + CodedInputStream input = data.CreateCodedInput(); + MergeFrom(input); + input.CheckLastTagWas(0); + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) { + CodedInputStream input = data.CreateCodedInput(); + MergeFrom(input, extensionRegistry); + input.CheckLastTagWas(0); + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(byte[] data) { + CodedInputStream input = CodedInputStream.CreateInstance(data); + MergeFrom(input); + input.CheckLastTagWas(0); + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) { + CodedInputStream input = CodedInputStream.CreateInstance(data); + MergeFrom(input, extensionRegistry); + input.CheckLastTagWas(0); + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(Stream input) { + CodedInputStream codedInput = CodedInputStream.CreateInstance(input); + MergeFrom(codedInput); + codedInput.CheckLastTagWas(0); + return ThisBuilder; + } + + public virtual TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) { + CodedInputStream codedInput = CodedInputStream.CreateInstance(input); + MergeFrom(codedInput, extensionRegistry); + codedInput.CheckLastTagWas(0); + return ThisBuilder; + } + + public virtual IBuilder SetField(FieldDescriptor field, object value) { + this[field] = value; + return ThisBuilder; + } + + public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) { + this[field, index] = value; + return ThisBuilder; + } + } +} diff --git a/src/ProtocolBuffers/AbstractMessage.cs b/src/ProtocolBuffers/AbstractMessage.cs new file mode 100644 index 00000000..d8b9e9e6 --- /dev/null +++ b/src/ProtocolBuffers/AbstractMessage.cs @@ -0,0 +1,181 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.Collections; +using System.Collections.Generic; +using System.IO; +using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Implementation of the non-generic IMessage interface as far as possible. + /// </summary> + public abstract class AbstractMessage<TMessage, TBuilder> : IMessage<TMessage, TBuilder> + where TMessage : AbstractMessage<TMessage, TBuilder> + where TBuilder : AbstractBuilder<TMessage, TBuilder> { + /// <summary> + /// The serialized size if it's already been computed, or null + /// if we haven't computed it yet. + /// </summary> + private int? memoizedSize = null; + + #region Unimplemented members of IMessage + public abstract MessageDescriptor DescriptorForType { get; } + public abstract IDictionary<FieldDescriptor, object> AllFields { get; } + public abstract bool HasField(FieldDescriptor field); + public abstract object this[FieldDescriptor field] { get; } + public abstract int GetRepeatedFieldCount(FieldDescriptor field); + public abstract object this[FieldDescriptor field, int index] { get; } + public abstract UnknownFieldSet UnknownFields { get; } + public abstract TMessage DefaultInstanceForType { get; } + public abstract TBuilder CreateBuilderForType(); + #endregion + + public IBuilder WeakCreateBuilderForType() { + return CreateBuilderForType(); + } + + public IMessage WeakDefaultInstanceForType { + get { return DefaultInstanceForType; } + } + + public virtual bool IsInitialized { + get { + // Check that all required fields are present. + foreach (FieldDescriptor field in DescriptorForType.Fields) { + if (field.IsRequired && !HasField(field)) { + return false; + } + } + + // Check that embedded messages are initialized. + foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) { + FieldDescriptor field = entry.Key; + if (field.MappedType == MappedType.Message) { + if (field.IsRepeated) { + // We know it's an IList<T>, but not the exact type - so + // IEnumerable is the best we can do. (C# generics aren't covariant yet.) + foreach (IMessage element in (IEnumerable) entry.Value) { + if (!element.IsInitialized) { + return false; + } + } + } else { + if (!((IMessage)entry.Value).IsInitialized) { + return false; + } + } + } + } + return true; + } + } + + public sealed override string ToString() { + return TextFormat.PrintToString(this); + } + + public virtual void WriteTo(CodedOutputStream output) { + foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) { + FieldDescriptor field = entry.Key; + if (field.IsRepeated) { + // We know it's an IList<T>, but not the exact type - so + // IEnumerable is the best we can do. (C# generics aren't covariant yet.) + foreach (object element in (IEnumerable)entry.Value) { + output.WriteField(field.FieldType, field.FieldNumber, element); + } + } else { + output.WriteField(field.FieldType, field.FieldNumber, entry.Value); + } + } + + UnknownFieldSet unknownFields = UnknownFields; + if (DescriptorForType.Options.MessageSetWireFormat) { + unknownFields.WriteAsMessageSetTo(output); + } else { + unknownFields.WriteTo(output); + } + } + + public virtual int SerializedSize { + get { + if (memoizedSize != null) { + return memoizedSize.Value; + } + + int size = 0; + foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) { + FieldDescriptor field = entry.Key; + if (field.IsRepeated) { + foreach (object element in (IEnumerable) entry.Value) { + size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, element); + } + } else { + size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, entry.Value); + } + } + + UnknownFieldSet unknownFields = UnknownFields; + if (DescriptorForType.Options.MessageSetWireFormat) { + size += unknownFields.SerializedSizeAsMessageSet; + } else { + size += unknownFields.SerializedSize; + } + + memoizedSize = size; + return size; + } + } + + public ByteString ToByteString() { + ByteString.CodedBuilder output = new ByteString.CodedBuilder(SerializedSize); + WriteTo(output.CodedOutput); + return output.Build(); + } + + public byte[] ToByteArray() { + byte[] result = new byte[SerializedSize]; + CodedOutputStream output = CodedOutputStream.CreateInstance(result); + WriteTo(output); + output.CheckNoSpaceLeft(); + return result; + } + + public void WriteTo(Stream output) { + CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output); + WriteTo(codedOutput); + codedOutput.Flush(); + } + + public override bool Equals(object other) { + if (other == this) { + return true; + } + IMessage otherMessage = other as IMessage; + if (otherMessage == null || otherMessage.DescriptorForType != DescriptorForType) { + return false; + } + return Dictionaries.Equals(AllFields, otherMessage.AllFields); + } + + public override int GetHashCode() { + int hash = 41; + hash = (19 * hash) + DescriptorForType.GetHashCode(); + hash = (53 * hash) + Dictionaries.GetHashCode(AllFields); + return hash; + } + } +} diff --git a/src/ProtocolBuffers/ByteString.cs b/src/ProtocolBuffers/ByteString.cs new file mode 100644 index 00000000..26816d9c --- /dev/null +++ b/src/ProtocolBuffers/ByteString.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections; +using System.Collections.Generic; +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.Text; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Immutable array of bytes. + /// TODO(jonskeet): Implement the common collection interfaces? + /// </summary> + public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString> { + + private static readonly ByteString empty = new ByteString(new byte[0]); + + private readonly byte[] bytes; + + /// <summary> + /// Constructs a new ByteString from the given byte array. The array is + /// *not* copied, and must not be modified after this constructor is called. + /// </summary> + private ByteString(byte[] bytes) { + this.bytes = bytes; + } + + /// <summary> + /// Returns an empty ByteString. + /// </summary> + public static ByteString Empty { + get { return empty; } + } + + /// <summary> + /// Returns the length of this ByteString in bytes. + /// </summary> + public int Length { + get { return bytes.Length; } + } + + public bool IsEmpty { + get { return Length == 0; } + } + + public byte[] ToByteArray() { + return (byte[])bytes.Clone(); + } + + /// <summary> + /// Constructs a ByteString from the given array. The contents + /// are copied, so further modifications to the array will not + /// be reflected in the returned ByteString. + /// </summary> + public static ByteString CopyFrom(byte[] bytes) { + return new ByteString((byte[]) bytes.Clone()); + } + + /// <summary> + /// Constructs a ByteString from a portion of a byte array. + /// </summary> + public static ByteString CopyFrom(byte[] bytes, int offset, int count) { + byte[] portion = new byte[count]; + Array.Copy(bytes, offset, portion, 0, count); + return new ByteString(portion); + } + + /// <summary> + /// Creates a new ByteString by encoding the specified text with + /// the given encoding. + /// </summary> + public static ByteString CopyFrom(string text, Encoding encoding) { + return new ByteString(encoding.GetBytes(text)); + } + + /// <summary> + /// Creates a new ByteString by encoding the specified text in UTF-8. + /// </summary> + public static ByteString CopyFromUtf8(string text) { + return CopyFrom(text, Encoding.UTF8); + } + + /// <summary> + /// Retuns the byte at the given index. + /// </summary> + public byte this[int index] { + get { return bytes[index]; } + } + + public string ToString(Encoding encoding) { + return encoding.GetString(bytes); + } + + public string ToStringUtf8() { + return ToString(Encoding.UTF8); + } + + public IEnumerator<byte> GetEnumerator() { + return ((IEnumerable<byte>) bytes).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + /// <summary> + /// Creates a CodedInputStream from this ByteString's data. + /// </summary> + public CodedInputStream CreateCodedInput() { + + // We trust CodedInputStream not to reveal the provided byte array or modify it + return CodedInputStream.CreateInstance(bytes); + } + + // TODO(jonskeet): CopyTo if it turns out to be required + + public override bool Equals(object obj) { + ByteString other = obj as ByteString; + if (obj == null) { + return false; + } + return Equals(other); + } + + public override int GetHashCode() { + int ret = 23; + foreach (byte b in bytes) { + ret = (ret << 8) | b; + } + return ret; + } + + public bool Equals(ByteString other) { + if (other.bytes.Length != bytes.Length) { + return false; + } + for (int i = 0; i < bytes.Length; i++) { + if (other.bytes[i] != bytes[i]) { + return false; + } + } + 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); + } + + public 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); + } + + public CodedOutputStream CodedOutput { + get { + return output; + } + } + } + } +} diff --git a/src/ProtocolBuffers/CodedInputStream.cs b/src/ProtocolBuffers/CodedInputStream.cs new file mode 100644 index 00000000..30969820 --- /dev/null +++ b/src/ProtocolBuffers/CodedInputStream.cs @@ -0,0 +1,843 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// Readings and decodes protocol message fields. + /// </summary> + /// <remarks> + /// 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. + /// </remarks> + public sealed class CodedInputStream { + private readonly byte[] buffer; + private int bufferSize; + private int bufferSizeAfterLimit = 0; + private int bufferPos = 0; + private readonly Stream input; + private uint lastTag = 0; + + const int DefaultRecursionLimit = 64; + const int DefaultSizeLimit = 64 << 20; // 64MB + const int BufferSize = 4096; + + /// <summary> + /// The total number of bytes read before the current buffer. The + /// total bytes read up to the current position can be computed as + /// totalBytesRetired + bufferPos. + /// </summary> + private int totalBytesRetired = 0; + + /// <summary> + /// The absolute position of the end of the current message. + /// </summary> + private int currentLimit = int.MaxValue; + + /// <summary> + /// <see cref="SetRecursionLimit"/> + /// </summary> + private int recursionDepth = 0; + private int recursionLimit = DefaultRecursionLimit; + + /// <summary> + /// <see cref="SetSizeLimit"/> + /// </summary> + private int sizeLimit = DefaultSizeLimit; + + #region Construction + /// <summary> + /// Creates a new CodedInputStream reading data from the given + /// stream. + /// </summary> + public static CodedInputStream CreateInstance(Stream input) { + return new CodedInputStream(input); + } + + /// <summary> + /// Creates a new CodedInputStream reading data from the given + /// byte array. + /// </summary> + public static CodedInputStream CreateInstance(byte[] buf) { + return new CodedInputStream(buf); + } + + private CodedInputStream(byte[] buffer) { + this.buffer = buffer; + this.bufferSize = buffer.Length; + this.input = null; + } + + private CodedInputStream(Stream input) { + this.buffer = new byte[BufferSize]; + this.bufferSize = 0; + this.input = input; + } + #endregion + + #region Validation + /// <summary> + /// Verifies that the last call to ReadTag() returned the given tag value. + /// This is used to verify that a nested group ended with the correct + /// end tag. + /// </summary> + /// <exception cref="InvalidProtocolBufferException">The last + /// tag read was not the one specified</exception> + public void CheckLastTagWas(uint value) { + if (lastTag != value) { + throw InvalidProtocolBufferException.InvalidEndTag(); + } + } + #endregion + + #region Reading of tags etc + /// <summary> + /// Attempt to read a field tag, returning 0 if we have reached the end + /// of the input data. Protocol message parsers use this to read tags, + /// since a protocol message may legally end wherever a tag occurs, and + /// zero is not a valid tag number. + /// </summary> + public uint ReadTag() { + if (bufferPos == bufferSize && !RefillBuffer(false)) { + lastTag = 0; + return 0; + } + + lastTag = ReadRawVarint32(); + if (lastTag == 0) { + // If we actually read zero, that's not a valid tag. + throw InvalidProtocolBufferException.InvalidTag(); + } + return lastTag; + } + + /// <summary> + /// Read a double field from the stream. + /// </summary> + public double ReadDouble() { + // TODO(jonskeet): Test this on different endiannesses + return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64()); + } + + /// <summary> + /// Read a float field from the stream. + /// </summary> + public float ReadFloat() { + // TODO(jonskeet): Test this on different endiannesses + uint raw = ReadRawLittleEndian32(); + byte[] rawBytes = BitConverter.GetBytes(raw); + return BitConverter.ToSingle(rawBytes, 0); + } + + /// <summary> + /// Read a uint64 field from the stream. + /// </summary> + public ulong ReadUInt64() { + return ReadRawVarint64(); + } + + /// <summary> + /// Read an int64 field from the stream. + /// </summary> + public long ReadInt64() { + return (long) ReadRawVarint64(); + } + + /// <summary> + /// Read an int32 field from the stream. + /// </summary> + public int ReadInt32() { + return (int) ReadRawVarint32(); + } + + /// <summary> + /// Read a fixed64 field from the stream. + /// </summary> + public ulong ReadFixed64() { + return ReadRawLittleEndian64(); + } + + /// <summary> + /// Read a fixed32 field from the stream. + /// </summary> + public uint ReadFixed32() { + return ReadRawLittleEndian32(); + } + + /// <summary> + /// Read a bool field from the stream. + /// </summary> + public bool ReadBool() { + return ReadRawVarint32() != 0; + } + + /// <summary> + /// Reads a string field from the stream. + /// </summary> + public String ReadString() { + int size = (int) ReadRawVarint32(); + if (size < bufferSize - bufferPos && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + String result = Encoding.UTF8.GetString(buffer, bufferPos, size); + bufferPos += size; + return result; + } else { + // Slow path: Build a byte array first then copy it. + return Encoding.UTF8.GetString(ReadRawBytes(size)); + } + } + + /// <summary> + /// Reads a group field value from the stream. + /// </summary> + public void ReadGroup(int fieldNumber, IBuilder builder, + ExtensionRegistry extensionRegistry) { + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + ++recursionDepth; + builder.WeakMergeFrom(this, extensionRegistry); + CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); + --recursionDepth; + } + + /// <summary> + /// Reads a group field value from the stream and merges it into the given + /// UnknownFieldSet. + /// </summary> + public void ReadUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder) { + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + ++recursionDepth; + builder.MergeFrom(this); + CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); + --recursionDepth; + } + + /// <summary> + /// Reads an embedded message field value from the stream. + /// </summary> + public void ReadMessage(IBuilder builder, ExtensionRegistry extensionRegistry) { + int length = (int) ReadRawVarint32(); + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + int oldLimit = PushLimit(length); + ++recursionDepth; + builder.WeakMergeFrom(this, extensionRegistry); + CheckLastTagWas(0); + --recursionDepth; + PopLimit(oldLimit); + } + + /// <summary> + /// Reads a bytes field value from the stream. + /// </summary> + public ByteString ReadBytes() { + int size = (int) ReadRawVarint32(); + if (size < bufferSize - bufferPos && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + ByteString result = ByteString.CopyFrom(buffer, bufferPos, size); + bufferPos += size; + return result; + } else { + // Slow path: Build a byte array first then copy it. + return ByteString.CopyFrom(ReadRawBytes(size)); + } + } + + /// <summary> + /// Reads a uint32 field value from the stream. + /// </summary> + public uint ReadUInt32() { + return ReadRawVarint32(); + } + + /// <summary> + /// Reads an enum field value from the stream. The caller is responsible + /// for converting the numeric value to an actual enum. + /// </summary> + public int ReadEnum() { + return (int) ReadRawVarint32(); + } + + /// <summary> + /// Reads an sfixed32 field value from the stream. + /// </summary> + public int ReadSFixed32() { + return (int) ReadRawLittleEndian32(); + } + + /// <summary> + /// Reads an sfixed64 field value from the stream. + /// </summary> + public long ReadSFixed64() { + return (long) ReadRawLittleEndian64(); + } + + /// <summary> + /// Reads an sint32 field value from the stream. + /// </summary> + public int ReadSInt32() { + return DecodeZigZag32(ReadRawVarint32()); + } + + /// <summary> + /// Reads an sint64 field value from the stream. + /// </summary> + public long ReadSInt64() { + return DecodeZigZag64(ReadRawVarint64()); + } + + /// <summary> + /// Reads a field of any primitive type. Enums, groups and embedded + /// messages are not handled by this method. + /// </summary> + public object ReadPrimitiveField(FieldType fieldType) { + switch (fieldType) { + case FieldType.Double: return ReadDouble(); + case FieldType.Float: return ReadFloat(); + case FieldType.Int64: return ReadInt64(); + case FieldType.UInt64: return ReadUInt64(); + case FieldType.Int32: return ReadInt32(); + case FieldType.Fixed64: return ReadFixed64(); + case FieldType.Fixed32: return ReadFixed32(); + case FieldType.Bool: return ReadBool(); + case FieldType.String: return ReadString(); + case FieldType.Bytes: return ReadBytes(); + case FieldType.UInt32: return ReadUInt32(); + case FieldType.SFixed32: return ReadSFixed32(); + case FieldType.SFixed64: return ReadSFixed64(); + case FieldType.SInt32: return ReadSInt32(); + case FieldType.SInt64: return ReadSInt64(); + case FieldType.Group: + throw new ArgumentException("ReadPrimitiveField() cannot handle nested groups."); + case FieldType.Message: + throw new ArgumentException("ReadPrimitiveField() cannot handle embedded messages."); + // We don't handle enums because we don't know what to do if the + // value is not recognized. + case FieldType.Enum: + throw new ArgumentException("ReadPrimitiveField() cannot handle enums."); + default: + throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); + } + } + + #endregion + + #region Underlying reading primitives + + /// <summary> + /// Same code as ReadRawVarint32, but read each byte individually, checking for + /// buffer overflow. + /// </summary> + private uint SlowReadRawVarint32() { + int tmp = ReadRawByte(); + if (tmp < 128) { + return (uint)tmp; + } + int result = tmp & 0x7f; + if ((tmp = ReadRawByte()) < 128) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if ((tmp = ReadRawByte()) < 128) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if ((tmp = ReadRawByte()) < 128) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + result |= (tmp = ReadRawByte()) << 28; + if (tmp >= 128) { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) { + if (ReadRawByte() < 128) return (uint)result; + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + } + } + } + return (uint)result; + } + + /// <summary> + /// Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. + /// This method is optimised for the case where we've got lots of data in the buffer. + /// That means we can check the size just once, then just read directly from the buffer + /// without constant rechecking of the buffer length. + /// </summary> + public uint ReadRawVarint32() { + if (bufferPos + 5 > bufferSize) { + return SlowReadRawVarint32(); + } + + int tmp = buffer[bufferPos++]; + if (tmp < 128) { + return (uint)tmp; + } + int result = tmp & 0x7f; + if ((tmp = buffer[bufferPos++]) < 128) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if ((tmp = buffer[bufferPos++]) < 128) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if ((tmp = buffer[bufferPos++]) < 128) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + result |= (tmp = buffer[bufferPos++]) << 28; + if (tmp >= 128) { + // Discard upper 32 bits. + // Note that this has to use ReadRawByte() as we only ensure we've + // got at least 5 bytes at the start of the method. This lets us + // use the fast path in more cases, and we rarely hit this section of code. + for (int i = 0; i < 5; i++) { + if (ReadRawByte() < 128) return (uint)result; + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + } + } + } + return (uint)result; + } + + /// <summary> + /// Read a raw varint from the stream. + /// </summary> + public ulong ReadRawVarint64() { + int shift = 0; + ulong result = 0; + while (shift < 64) { + byte b = ReadRawByte(); + result |= (ulong)(b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + + /// <summary> + /// Read a 32-bit little-endian integer from the stream. + /// </summary> + public uint ReadRawLittleEndian32() { + uint b1 = ReadRawByte(); + uint b2 = ReadRawByte(); + uint b3 = ReadRawByte(); + uint b4 = ReadRawByte(); + return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + } + + /// <summary> + /// Read a 64-bit little-endian integer from the stream. + /// </summary> + public ulong ReadRawLittleEndian64() { + ulong b1 = ReadRawByte(); + ulong b2 = ReadRawByte(); + ulong b3 = ReadRawByte(); + ulong b4 = ReadRawByte(); + ulong b5 = ReadRawByte(); + ulong b6 = ReadRawByte(); + ulong b7 = ReadRawByte(); + ulong b8 = ReadRawByte(); + return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) + | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); + } + #endregion + + /// <summary> + /// Decode a 32-bit value with ZigZag encoding. + /// </summary> + /// <remarks> + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// </remarks> + public static int DecodeZigZag32(uint n) { + return (int)(n >> 1) ^ -(int)(n & 1); + } + + /// <summary> + /// Decode a 32-bit value with ZigZag encoding. + /// </summary> + /// <remarks> + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// </remarks> + public static long DecodeZigZag64(ulong n) { + return (long)(n >> 1) ^ -(long)(n & 1); + } + + /// <summary> + /// Set the maximum message recursion depth. + /// </summary> + /// <remarks> + /// In order to prevent malicious + /// messages from causing stack overflows, CodedInputStream limits + /// how deeply messages may be nested. The default limit is 64. + /// </remarks> + public int SetRecursionLimit(int limit) { + if (limit < 0) { + throw new ArgumentOutOfRangeException("Recursion limit cannot be negative: " + limit); + } + int oldLimit = recursionLimit; + recursionLimit = limit; + return oldLimit; + } + + /// <summary> + /// Set the maximum message size. + /// </summary> + /// <remarks> + /// In order to prevent malicious messages from exhausting memory or + /// causing integer overflows, CodedInputStream limits how large a message may be. + /// The default limit is 64MB. You should set this limit as small + /// as you can without harming your app's functionality. Note that + /// size limits only apply when reading from an InputStream, not + /// when constructed around a raw byte array (nor with ByteString.NewCodedInput). + /// </remarks> + public int SetSizeLimit(int limit) { + if (limit < 0) { + throw new ArgumentOutOfRangeException("Size limit cannot be negative: " + limit); + } + int oldLimit = sizeLimit; + sizeLimit = limit; + return oldLimit; + } + + #region Internal reading and buffer management + /// <summary> + /// Sets currentLimit to (current position) + byteLimit. This is called + /// when descending into a length-delimited embedded message. The previous + /// limit is returned. + /// </summary> + /// <returns>The old limit.</returns> + public int PushLimit(int byteLimit) { + if (byteLimit < 0) { + throw InvalidProtocolBufferException.NegativeSize(); + } + byteLimit += totalBytesRetired + bufferPos; + int oldLimit = currentLimit; + if (byteLimit > oldLimit) { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + currentLimit = byteLimit; + + RecomputeBufferSizeAfterLimit(); + + return oldLimit; + } + + private void RecomputeBufferSizeAfterLimit() { + bufferSize += bufferSizeAfterLimit; + int bufferEnd = totalBytesRetired + bufferSize; + if (bufferEnd > currentLimit) { + // Limit is in current buffer. + bufferSizeAfterLimit = bufferEnd - currentLimit; + bufferSize -= bufferSizeAfterLimit; + } else { + bufferSizeAfterLimit = 0; + } + } + + /// <summary> + /// Discards the current limit, returning the previous limit. + /// </summary> + public void PopLimit(int oldLimit) { + currentLimit = oldLimit; + RecomputeBufferSizeAfterLimit(); + } + + /// <summary> + /// Called when buffer is empty to read more bytes from the + /// input. If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that + /// either there will be at least one byte in the buffer when it returns + /// or it will throw an exception. If <paramref name="mustSucceed"/> is false, + /// RefillBuffer() returns false if no more bytes were available. + /// </summary> + /// <param name="mustSucceed"></param> + /// <returns></returns> + private bool RefillBuffer(bool mustSucceed) { + if (bufferPos < bufferSize) { + throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty."); + } + + if (totalBytesRetired + bufferSize == currentLimit) { + // Oops, we hit a limit. + if (mustSucceed) { + throw InvalidProtocolBufferException.TruncatedMessage(); + } else { + return false; + } + } + + totalBytesRetired += bufferSize; + + bufferPos = 0; + bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length); + if (bufferSize == 0) { + if (mustSucceed) { + throw InvalidProtocolBufferException.TruncatedMessage(); + } else { + return false; + } + } else { + RecomputeBufferSizeAfterLimit(); + int totalBytesRead = + totalBytesRetired + bufferSize + bufferSizeAfterLimit; + if (totalBytesRead > sizeLimit || totalBytesRead < 0) { + throw InvalidProtocolBufferException.SizeLimitExceeded(); + } + return true; + } + } + + /// <summary> + /// Read one byte from the input. + /// </summary> + /// <exception cref="InvalidProtocolBufferException"> + /// he end of the stream or the current limit was reached + /// </exception> + public byte ReadRawByte() { + if (bufferPos == bufferSize) { + RefillBuffer(true); + } + return buffer[bufferPos++]; + } + + /// <summary> + /// Read a fixed size of bytes from the input. + /// </summary> + /// <exception cref="InvalidProtocolBufferException"> + /// the end of the stream or the current limit was reached + /// </exception> + public byte[] ReadRawBytes(int size) { + if (size < 0) { + throw InvalidProtocolBufferException.NegativeSize(); + } + + if (totalBytesRetired + bufferPos + size > currentLimit) { + // Read to the end of the stream anyway. + SkipRawBytes(currentLimit - totalBytesRetired - bufferPos); + // Then fail. + throw InvalidProtocolBufferException.TruncatedMessage(); + } + + if (size <= bufferSize - bufferPos) { + // We have all the bytes we need already. + byte[] bytes = new byte[size]; + Array.Copy(buffer, bufferPos, bytes, 0, size); + bufferPos += size; + return bytes; + } else if (size < BufferSize) { + // Reading more bytes than are in the buffer, but not an excessive number + // of bytes. We can safely allocate the resulting array ahead of time. + + // First copy what we have. + byte[] bytes = new byte[size]; + int pos = bufferSize - bufferPos; + Array.Copy(buffer, bufferPos, bytes, 0, pos); + bufferPos = bufferSize; + + // We want to use RefillBuffer() and then copy from the buffer into our + // byte array rather than reading directly into our byte array because + // the input may be unbuffered. + RefillBuffer(true); + + while (size - pos > bufferSize) { + Array.Copy(buffer, 0, bytes, pos, bufferSize); + pos += bufferSize; + bufferPos = bufferSize; + RefillBuffer(true); + } + + Array.Copy(buffer, 0, bytes, pos, size - pos); + bufferPos = size - pos; + + return bytes; + } else { + // The size is very large. For security reasons, we can't allocate the + // entire byte array yet. The size comes directly from the input, so a + // maliciously-crafted message could provide a bogus very large size in + // order to trick the app into allocating a lot of memory. We avoid this + // by allocating and reading only a small chunk at a time, so that the + // malicious message must actually *be* extremely large to cause + // problems. Meanwhile, we limit the allowed size of a message elsewhere. + + // Remember the buffer markers since we'll have to copy the bytes out of + // it later. + int originalBufferPos = bufferPos; + int originalBufferSize = bufferSize; + + // Mark the current buffer consumed. + totalBytesRetired += bufferSize; + bufferPos = 0; + bufferSize = 0; + + // Read all the rest of the bytes we need. + int sizeLeft = size - (originalBufferSize - originalBufferPos); + List<byte[]> chunks = new List<byte[]>(); + + while (sizeLeft > 0) { + byte[] chunk = new byte[Math.Min(sizeLeft, BufferSize)]; + int pos = 0; + while (pos < chunk.Length) { + int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos); + if (n <= 0) { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + totalBytesRetired += n; + pos += n; + } + sizeLeft -= chunk.Length; + chunks.Add(chunk); + } + + // OK, got everything. Now concatenate it all into one buffer. + byte[] bytes = new byte[size]; + + // Start by copying the leftover bytes from this.buffer. + int newPos = originalBufferSize - originalBufferPos; + Array.Copy(buffer, originalBufferPos, bytes, 0, newPos); + + // And now all the chunks. + foreach (byte[] chunk in chunks) { + Array.Copy(chunk, 0, bytes, newPos, chunk.Length); + newPos += chunk.Length; + } + + // Done. + return bytes; + } + } + + /// <summary> + /// Reads and discards a single field, given its tag value. + /// </summary> + /// <returns>false if the tag is an end-group tag, in which case + /// nothing is skipped. Otherwise, returns true.</returns> + public bool SkipField(uint tag) { + switch (WireFormat.GetTagWireType(tag)) { + case WireFormat.WireType.Varint: + ReadInt32(); + return true; + case WireFormat.WireType.Fixed64: + ReadRawLittleEndian64(); + return true; + case WireFormat.WireType.LengthDelimited: + SkipRawBytes((int) ReadRawVarint32()); + return true; + case WireFormat.WireType.StartGroup: + SkipMessage(); + CheckLastTagWas( + WireFormat.MakeTag(WireFormat.GetTagFieldNumber(tag), + WireFormat.WireType.EndGroup)); + return true; + case WireFormat.WireType.EndGroup: + return false; + case WireFormat.WireType.Fixed32: + ReadRawLittleEndian32(); + return true; + default: + throw InvalidProtocolBufferException.InvalidWireType(); + } + } + + /// <summary> + /// Reads and discards an entire message. This will read either until EOF + /// or until an endgroup tag, whichever comes first. + /// </summary> + public void SkipMessage() { + while (true) { + uint tag = ReadTag(); + if (tag == 0 || !SkipField(tag)) { + return; + } + } + } + + /// <summary> + /// Reads and discards <paramref name="size"/> bytes. + /// </summary> + /// <exception cref="InvalidProtocolBufferException">the end of the stream + /// or the current limit was reached</exception> + public void SkipRawBytes(int size) { + if (size < 0) { + throw InvalidProtocolBufferException.NegativeSize(); + } + + if (totalBytesRetired + bufferPos + size > currentLimit) { + // Read to the end of the stream anyway. + SkipRawBytes(currentLimit - totalBytesRetired - bufferPos); + // Then fail. + throw InvalidProtocolBufferException.TruncatedMessage(); + } + + if (size < bufferSize - bufferPos) { + // We have all the bytes we need already. + bufferPos += size; + } else { + // Skipping more bytes than are in the buffer. First skip what we have. + int pos = bufferSize - bufferPos; + totalBytesRetired += pos; + bufferPos = 0; + bufferSize = 0; + + // Then skip directly from the InputStream for the rest. + if (pos < size) { + // TODO(jonskeet): Java implementation uses skip(). Not sure whether this is really equivalent... + if (input == null) { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + input.Seek(size - pos, SeekOrigin.Current); + if (input.Position > input.Length) { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + totalBytesRetired += size - pos; + } + } + } + #endregion + } +} diff --git a/src/ProtocolBuffers/CodedOutputStream.cs b/src/ProtocolBuffers/CodedOutputStream.cs new file mode 100644 index 00000000..0abfa39a --- /dev/null +++ b/src/ProtocolBuffers/CodedOutputStream.cs @@ -0,0 +1,765 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.IO; +using System.Text; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// Encodes and writes protocol message fields. + /// </summary> + /// <remarks> + /// 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.) + /// </remarks> + public sealed class CodedOutputStream { + /// <summary> + /// The buffer size used by CreateInstance(Stream). + /// </summary> + public static readonly int DefaultBufferSize = 4096; + + private readonly byte[] buffer; + private readonly int limit; + private int position; + private readonly Stream output; + + #region Construction + private CodedOutputStream(byte[] buffer, int offset, int length) { + this.output = null; + this.buffer = buffer; + this.position = offset; + this.limit = offset + length; + } + + private CodedOutputStream(Stream output, byte[] buffer) { + this.output = output; + this.buffer = buffer; + this.position = 0; + this.limit = buffer.Length; + } + + /// <summary> + /// Creates a new CodedOutputStream which write to the given stream. + /// </summary> + public static CodedOutputStream CreateInstance(Stream output) { + return CreateInstance(output, DefaultBufferSize); + } + + /// <summary> + /// Creates a new CodedOutputStream which write to the given stream and uses + /// the specified buffer size. + /// </summary> + public static CodedOutputStream CreateInstance(Stream output, int bufferSize) { + return new CodedOutputStream(output, new byte[bufferSize]); + } + + /// <summary> + /// Creates a new CodedOutputStream that writes directly to the given + /// byte array. If more bytes are written than fit in the array, + /// OutOfSpaceException will be thrown. + /// </summary> + public static CodedOutputStream CreateInstance(byte[] flatArray) { + return CreateInstance(flatArray, 0, flatArray.Length); + } + + /// <summary> + /// Creates a new CodedOutputStream that writes directly to the given + /// byte array slice. If more bytes are written than fit in the array, + /// OutOfSpaceException will be thrown. + /// </summary> + public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length) { + return new CodedOutputStream(flatArray, offset, length); + } + #endregion + + #region Writing of tags etc + /// <summary> + /// Writes a double field value, including tag, to the stream. + /// </summary> + public void WriteDouble(int fieldNumber, double value) { + // TODO(jonskeet): Test this on different endiannesses + WriteTag(fieldNumber, WireFormat.WireType.Fixed64); + WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value)); + } + + /// <summary> + /// Writes a float field value, including tag, to the stream. + /// </summary> + public void WriteFloat(int fieldNumber, float value) { + WriteTag(fieldNumber, WireFormat.WireType.Fixed32); + // TODO(jonskeet): Test this on different endiannesses + byte[] rawBytes = BitConverter.GetBytes(value); + uint asInteger = BitConverter.ToUInt32(rawBytes, 0); + WriteRawLittleEndian32(asInteger); + } + + /// <summary> + /// Writes a uint64 field value, including tag, to the stream. + /// </summary> + public void WriteUInt64(int fieldNumber, ulong value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + WriteRawVarint64(value); + } + + /// <summary> + /// Writes an int64 field value, including tag, to the stream. + /// </summary> + public void WriteInt64(int fieldNumber, long value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + WriteRawVarint64((ulong)value); + } + + /// <summary> + /// Writes an int32 field value, including tag, to the stream. + /// </summary> + public void WriteInt32(int fieldNumber, int value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + if (value >= 0) { + WriteRawVarint32((uint)value); + } else { + // Must sign-extend. + WriteRawVarint64((ulong)value); + } + } + + /// <summary> + /// Writes a fixed64 field value, including tag, to the stream. + /// </summary> + public void WriteFixed64(int fieldNumber, ulong value) { + WriteTag(fieldNumber, WireFormat.WireType.Fixed64); + WriteRawLittleEndian64(value); + } + + /// <summary> + /// Writes a fixed32 field value, including tag, to the stream. + /// </summary> + public void WriteFixed32(int fieldNumber, uint value) { + WriteTag(fieldNumber, WireFormat.WireType.Fixed32); + WriteRawLittleEndian32(value); + } + + /// <summary> + /// Writes a bool field value, including tag, to the stream. + /// </summary> + public void WriteBool(int fieldNumber, bool value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + WriteRawByte(value ? (byte)1 : (byte)0); + } + + /// <summary> + /// Writes a string field value, including tag, to the stream. + /// </summary> + public void WriteString(int fieldNumber, string value) { + WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); + // Optimise the case where we have enough space to write + // the string directly to the buffer, which should be common. + int length = Encoding.UTF8.GetByteCount(value); + WriteRawVarint32((uint) length); + if (limit - position >= length) { + Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position); + position += length; + } else { + byte[] bytes = Encoding.UTF8.GetBytes(value); + WriteRawBytes(bytes); + } + } + + /// <summary> + /// Writes a group field value, including tag, to the stream. + /// </summary> + public void WriteGroup(int fieldNumber, IMessage value) { + WriteTag(fieldNumber, WireFormat.WireType.StartGroup); + value.WriteTo(this); + WriteTag(fieldNumber, WireFormat.WireType.EndGroup); + } + + public void WriteUnknownGroup(int fieldNumber, UnknownFieldSet value) { + WriteTag(fieldNumber, WireFormat.WireType.StartGroup); + value.WriteTo(this); + WriteTag(fieldNumber, WireFormat.WireType.EndGroup); + } + + public void WriteMessage(int fieldNumber, IMessage value) { + WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); + WriteRawVarint32((uint)value.SerializedSize); + value.WriteTo(this); + } + + public void WriteBytes(int fieldNumber, ByteString value) { + // TODO(jonskeet): Optimise this! (No need to copy the bytes twice.) + WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); + byte[] bytes = value.ToByteArray(); + WriteRawVarint32((uint)bytes.Length); + WriteRawBytes(bytes); + } + + public void WriteUInt32(int fieldNumber, uint value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + WriteRawVarint32(value); + } + + public void WriteEnum(int fieldNumber, int value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + WriteRawVarint32((uint)value); + } + + public void WriteSFixed32(int fieldNumber, int value) { + WriteTag(fieldNumber, WireFormat.WireType.Fixed32); + WriteRawLittleEndian32((uint)value); + } + + public void WriteSFixed64(int fieldNumber, long value) { + WriteTag(fieldNumber, WireFormat.WireType.Fixed64); + WriteRawLittleEndian64((ulong)value); + } + + public void WriteSInt32(int fieldNumber, int value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + WriteRawVarint32(EncodeZigZag32(value)); + } + + public void WriteSInt64(int fieldNumber, long value) { + WriteTag(fieldNumber, WireFormat.WireType.Varint); + WriteRawVarint64(EncodeZigZag64(value)); + } + + public void WriteMessageSetExtension(int fieldNumber, IMessage value) { + WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup); + WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber); + WriteMessage(WireFormat.MessageSetField.Message, value); + WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup); + } + + public void WriteRawMessageSetExtension(int fieldNumber, ByteString value) { + WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup); + WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber); + WriteBytes(WireFormat.MessageSetField.Message, value); + WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup); + } + + public void WriteField(FieldType fieldType, int fieldNumber, object value) { + switch (fieldType) { + case FieldType.Double: WriteDouble(fieldNumber, (double)value); break; + case FieldType.Float: WriteFloat(fieldNumber, (float)value); break; + case FieldType.Int64: WriteInt64(fieldNumber, (long)value); break; + case FieldType.UInt64: WriteUInt64(fieldNumber, (ulong)value); break; + case FieldType.Int32: WriteInt32(fieldNumber, (int)value); break; + case FieldType.Fixed64: WriteFixed64(fieldNumber, (ulong)value); break; + case FieldType.Fixed32: WriteFixed32(fieldNumber, (uint)value); break; + case FieldType.Bool: WriteBool(fieldNumber, (bool)value); break; + case FieldType.String: WriteString(fieldNumber, (string)value); break; + case FieldType.Group: WriteGroup(fieldNumber, (IMessage)value); break; + case FieldType.Message: WriteMessage(fieldNumber, (IMessage)value); break; + case FieldType.Bytes: WriteBytes(fieldNumber, (ByteString)value); break; + case FieldType.UInt32: WriteUInt32(fieldNumber, (uint)value); break; + case FieldType.SFixed32: WriteSFixed32(fieldNumber, (int)value); break; + case FieldType.SFixed64: WriteSFixed64(fieldNumber, (long)value); break; + case FieldType.SInt32: WriteSInt32(fieldNumber, (int)value); break; + case FieldType.SInt64: WriteSInt64(fieldNumber, (long)value); break; + case FieldType.Enum: WriteEnum(fieldNumber, ((EnumValueDescriptor)value).Number); + break; + } + } + + #endregion + + #region Underlying writing primitives + /// <summary> + /// Encodes and writes a tag. + /// </summary> + public void WriteTag(int fieldNumber, WireFormat.WireType type) { + WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type)); + } + + private void SlowWriteRawVarint32(uint value) { + while (true) { + if ((value & ~0x7F) == 0) { + WriteRawByte(value); + return; + } else { + WriteRawByte((value & 0x7F) | 0x80); + value >>= 7; + } + } + } + + /// <summary> + /// Writes a 32 bit value as a varint. The fast route is taken when + /// there's enough buffer space left to whizz through without checking + /// for each byte; otherwise, we resort to calling WriteRawByte each time. + /// </summary> + public void WriteRawVarint32(uint value) { + if (position + 5 > limit) { + SlowWriteRawVarint32(value); + return; + } + + while (true) { + if ((value & ~0x7F) == 0) { + buffer[position++] = (byte) value; + return; + } else { + buffer[position++] = (byte)((value & 0x7F) | 0x80); + value >>= 7; + } + } + } + + public void WriteRawVarint64(ulong value) { + while (true) { + if ((value & ~0x7FUL) == 0) { + WriteRawByte((uint)value); + return; + } else { + WriteRawByte(((uint)value & 0x7F) | 0x80); + value >>= 7; + } + } + } + + public void WriteRawLittleEndian32(uint value) { + WriteRawByte((byte)value); + WriteRawByte((byte)(value >> 8)); + WriteRawByte((byte)(value >> 16)); + WriteRawByte((byte)(value >> 24)); + } + + public void WriteRawLittleEndian64(ulong value) { + WriteRawByte((byte)value); + WriteRawByte((byte)(value >> 8)); + WriteRawByte((byte)(value >> 16)); + WriteRawByte((byte)(value >> 24)); + WriteRawByte((byte)(value >> 32)); + WriteRawByte((byte)(value >> 40)); + WriteRawByte((byte)(value >> 48)); + WriteRawByte((byte)(value >> 56)); + } + + public void WriteRawByte(byte value) { + if (position == limit) { + RefreshBuffer(); + } + + buffer[position++] = value; + } + + public void WriteRawByte(uint value) { + WriteRawByte((byte)value); + } + + /// <summary> + /// Writes out an array of bytes. + /// </summary> + public void WriteRawBytes(byte[] value) { + WriteRawBytes(value, 0, value.Length); + } + + /// <summary> + /// Writes out part of an array of bytes. + /// </summary> + public void WriteRawBytes(byte[] value, int offset, int length) { + if (limit - position >= length) { + Array.Copy(value, offset, buffer, position, length); + // We have room in the current buffer. + position += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + int bytesWritten = limit - position; + Array.Copy(value, offset, buffer, position, bytesWritten); + offset += bytesWritten; + length -= bytesWritten; + position = limit; + RefreshBuffer(); + + // Now deal with the rest. + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + if (length <= limit) { + // Fits in new buffer. + Array.Copy(value, offset, buffer, 0, length); + position = length; + } else { + // Write is very big. Let's do it all at once. + output.Write(value, offset, length); + } + } + } + #endregion + + #region Size computations + + const int LittleEndian64Size = 8; + const int LittleEndian32Size = 4; + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// double field, including the tag. + /// </summary> + public static int ComputeDoubleSize(int fieldNumber, double value) { + return ComputeTagSize(fieldNumber) + LittleEndian64Size; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// float field, including the tag. + /// </summary> + public static int ComputeFloatSize(int fieldNumber, float value) { + return ComputeTagSize(fieldNumber) + LittleEndian32Size; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// uint64 field, including the tag. + /// </summary> + public static int ComputeUInt64Size(int fieldNumber, ulong value) { + return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size(value); + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// int64 field, including the tag. + /// </summary> + public static int ComputeInt64Size(int fieldNumber, long value) { + return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size((ulong)value); + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// int32 field, including the tag. + /// </summary> + public static int ComputeInt32Size(int fieldNumber, int value) { + if (value >= 0) { + return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)value); + } else { + // Must sign-extend. + return ComputeTagSize(fieldNumber) + 10; + } + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// fixed64 field, including the tag. + /// </summary> + public static int ComputeFixed64Size(int fieldNumber, ulong value) { + return ComputeTagSize(fieldNumber) + LittleEndian64Size; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// fixed32 field, including the tag. + /// </summary> + public static int ComputeFixed32Size(int fieldNumber, uint value) { + return ComputeTagSize(fieldNumber) + LittleEndian32Size; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// bool field, including the tag. + /// </summary> + public static int ComputeBoolSize(int fieldNumber, bool value) { + return ComputeTagSize(fieldNumber) + 1; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// string field, including the tag. + /// </summary> + public static int ComputeStringSize(int fieldNumber, String value) { + int byteArraySize = Encoding.UTF8.GetByteCount(value); + return ComputeTagSize(fieldNumber) + + ComputeRawVarint32Size((uint)byteArraySize) + + byteArraySize; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// group field, including the tag. + /// </summary> + public static int ComputeGroupSize(int fieldNumber, IMessage value) { + return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// group field represented by an UnknownFieldSet, including the tag. + /// </summary> + public static int ComputeUnknownGroupSize(int fieldNumber, + UnknownFieldSet value) { + return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// embedded message field, including the tag. + /// </summary> + public static int ComputeMessageSize(int fieldNumber, IMessage value) { + int size = value.SerializedSize; + return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)size) + size; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// bytes field, including the tag. + /// </summary> + public static int ComputeBytesSize(int fieldNumber, ByteString value) { + return ComputeTagSize(fieldNumber) + + ComputeRawVarint32Size((uint)value.Length) + + value.Length; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// uint32 field, including the tag. + /// </summary> + public static int ComputeUInt32Size(int fieldNumber, uint value) { + return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size(value); + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// enum field, including the tag. The caller is responsible for + /// converting the enum value to its numeric value. + /// </summary> + public static int ComputeEnumSize(int fieldNumber, int value) { + return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)value); + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// sfixed32 field, including the tag. + /// </summary> + public static int ComputeSFixed32Size(int fieldNumber, int value) { + return ComputeTagSize(fieldNumber) + LittleEndian32Size; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// sfixed64 field, including the tag. + /// </summary> + public static int ComputeSFixed64Size(int fieldNumber, long value) { + return ComputeTagSize(fieldNumber) + LittleEndian64Size; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// sint32 field, including the tag. + /// </summary> + public static int ComputeSInt32Size(int fieldNumber, int value) { + return ComputeTagSize(fieldNumber) + + ComputeRawVarint32Size(EncodeZigZag32(value)); + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// sint64 field, including the tag. + /// </summary> + public static int ComputeSInt64Size(int fieldNumber, long value) { + return ComputeTagSize(fieldNumber) + + ComputeRawVarint64Size(EncodeZigZag64(value)); + } + + /* + * Compute the number of bytes that would be needed to encode a + * MessageSet extension to the stream. For historical reasons, + * the wire format differs from normal fields. + */ + /// <summary> + /// Compute the number of bytes that would be needed to encode a + /// MessageSet extension to the stream. For historical reasons, + /// the wire format differs from normal fields. + /// </summary> + public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessage value) { + return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 + + ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) + + ComputeMessageSize(WireFormat.MessageSetField.Message, value); + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode an + /// unparsed MessageSet extension field to the stream. For + /// historical reasons, the wire format differs from normal fields. + /// </summary> + public static int ComputeRawMessageSetExtensionSize(int fieldNumber, ByteString value) { + return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 + + ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) + + ComputeBytesSize(WireFormat.MessageSetField.Message, value); + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a varint. + /// </summary> + public static int ComputeRawVarint32Size(uint value) { + if ((value & (0xffffffff << 7)) == 0) return 1; + if ((value & (0xffffffff << 14)) == 0) return 2; + if ((value & (0xffffffff << 21)) == 0) return 3; + if ((value & (0xffffffff << 28)) == 0) return 4; + return 5; + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a varint. + /// </summary> + public static int ComputeRawVarint64Size(ulong value) { + if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; + if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; + if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; + if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; + if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; + if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; + if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; + if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; + if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; + return 10; + } + + + /* + * Compute the number of bytes that would be needed to encode a + * field of arbitrary type, including tag, to the stream. + * + * @param type The field's type. + * @param number The field's number. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(FieldDescriptor)} for + * this field. + */ + public static int ComputeFieldSize(FieldType fieldType, int fieldNumber, Object value) { + switch (fieldType) { + case FieldType.Double: return ComputeDoubleSize(fieldNumber, (double)value); + case FieldType.Float: return ComputeFloatSize(fieldNumber, (float)value); + case FieldType.Int64: return ComputeInt64Size(fieldNumber, (long)value); + case FieldType.UInt64: return ComputeUInt64Size(fieldNumber, (ulong)value); + case FieldType.Int32: return ComputeInt32Size(fieldNumber, (int)value); + case FieldType.Fixed64: return ComputeFixed64Size(fieldNumber, (ulong)value); + case FieldType.Fixed32: return ComputeFixed32Size(fieldNumber, (uint)value); + case FieldType.Bool: return ComputeBoolSize(fieldNumber, (bool)value); + case FieldType.String: return ComputeStringSize(fieldNumber, (string)value); + case FieldType.Group: return ComputeGroupSize(fieldNumber, (IMessage)value); + case FieldType.Message: return ComputeMessageSize(fieldNumber, (IMessage)value); + case FieldType.Bytes: return ComputeBytesSize(fieldNumber, (ByteString)value); + case FieldType.UInt32: return ComputeUInt32Size(fieldNumber, (uint)value); + case FieldType.SFixed32: return ComputeSFixed32Size(fieldNumber, (int)value); + case FieldType.SFixed64: return ComputeSFixed64Size(fieldNumber, (long)value); + case FieldType.SInt32: return ComputeSInt32Size(fieldNumber, (int)value); + case FieldType.SInt64: return ComputeSInt64Size(fieldNumber, (long)value); + case FieldType.Enum: return ComputeEnumSize(fieldNumber, ((EnumValueDescriptor)value).Number); + default: + throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); + } + } + + /// <summary> + /// Compute the number of bytes that would be needed to encode a tag. + /// </summary> + public static int ComputeTagSize(int fieldNumber) { + return ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0)); + } + #endregion + + /// <summary> + /// Encode a 32-bit value with ZigZag encoding. + /// </summary> + /// <remarks> + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// </remarks> + public static uint EncodeZigZag32(int n) { + // Note: the right-shift must be arithmetic + return (uint)((n << 1) ^ (n >> 31)); + } + + /// <summary> + /// Encode a 64-bit value with ZigZag encoding. + /// </summary> + /// <remarks> + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// </remarks> + public static ulong EncodeZigZag64(long n) { + return (ulong)((n << 1) ^ (n >> 63)); + } + + private void RefreshBuffer() { + if (output == null) { + // We're writing to a single buffer. + throw new OutOfSpaceException(); + } + + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + output.Write(buffer, 0, position); + position = 0; + } + + /// <summary> + /// Indicates that a CodedOutputStream wrapping a flat byte array + /// ran out of space. + /// </summary> + public sealed class OutOfSpaceException : IOException { + internal OutOfSpaceException() + : base("CodedOutputStream was writing to a flat byte array and ran out of space.") { + } + } + + public void Flush() { + if (output != null) { + RefreshBuffer(); + } + } + + /// <summary> + /// Verifies that SpaceLeft returns zero. It's common to create a byte array + /// that is exactly big enough to hold a message, then write to it with + /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that + /// the message was actually as big as expected, which can help bugs. + /// </summary> + public void CheckNoSpaceLeft() { + if (SpaceLeft != 0) { + throw new InvalidOperationException("Did not write as much data as expected."); + } + } + + /// <summary> + /// If writing to a flat array, returns the space left in the array. Otherwise, + /// throws an InvalidOperationException. + /// </summary> + public int SpaceLeft { + get { + if (output == null) { + return limit - position; + } else { + throw new InvalidOperationException( + "SpaceLeft can only be called on CodedOutputStreams that are " + + "writing to a flat array."); + } + } + } + } +}
\ No newline at end of file diff --git a/src/ProtocolBuffers/Collections/Dictionaries.cs b/src/ProtocolBuffers/Collections/Dictionaries.cs new file mode 100644 index 00000000..5ba02664 --- /dev/null +++ b/src/ProtocolBuffers/Collections/Dictionaries.cs @@ -0,0 +1,108 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Google.ProtocolBuffers.Collections { + + /// <summary> + /// Non-generic class with generic methods which proxy to the non-generic methods + /// in the generic class. + /// </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 (!object.Equals(leftEntry.Value, rightValue)) { + return false; + } + } else { + IEnumerator leftEnumerator = leftEnumerable.GetEnumerator(); + try { + foreach (object rightObject in rightEnumerable) { + if (!leftEnumerator.MoveNext()) { + return false; + } + if (!object.Equals(leftEnumerator.Current, rightObject)) { + return false; + } + } + if (leftEnumerator.MoveNext()) { + return false; + } + } finally { + if (leftEnumerator is IDisposable) { + ((IDisposable)leftEnumerator).Dispose(); + } + } + } + } + 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; + } + } +} diff --git a/src/ProtocolBuffers/Collections/Lists.cs b/src/ProtocolBuffers/Collections/Lists.cs new file mode 100644 index 00000000..b1b6b122 --- /dev/null +++ b/src/ProtocolBuffers/Collections/Lists.cs @@ -0,0 +1,56 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Google.ProtocolBuffers.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); + } + } + + /// <summary> + /// Utility class for dealing with lists. + /// </summary> + public static class Lists<T> { + + 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); + } + } +} diff --git a/src/ProtocolBuffers/Collections/PopsicleList.cs b/src/ProtocolBuffers/Collections/PopsicleList.cs new file mode 100644 index 00000000..4efe13d0 --- /dev/null +++ b/src/ProtocolBuffers/Collections/PopsicleList.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections; + +namespace Google.ProtocolBuffers.Collections { + /// <summary> + /// Proxies calls to a <see cref="List{T}" />, but allows the list + /// to be made read-only (with the <see cref="MakeReadOnly" /> method), + /// after which any modifying methods throw <see cref="NotSupportedException" />. + /// </summary> + public sealed class PopsicleList<T> : IList<T> { + + private readonly List<T> items = new List<T>(); + private bool readOnly = false; + + /// <summary> + /// Makes this list read-only ("freezes the popsicle"). From this + /// point on, mutating methods (Clear, Add etc) will throw a + /// NotSupportedException. There is no way of "defrosting" the list afterwards. + /// </summary> + public void MakeReadOnly() { + readOnly = true; + } + + public int IndexOf(T item) { + return items.IndexOf(item); + } + + public void Insert(int index, T item) { + ValidateModification(); + items.Insert(index, item); + } + + public void RemoveAt(int index) { + ValidateModification(); + items.RemoveAt(index); + } + + public T this[int index] { + get { + return items[index]; + } + set { + ValidateModification(); + items[index] = value; + } + } + + public void Add(T item) { + ValidateModification(); + items.Add(item); + } + + public void Clear() { + ValidateModification(); + items.Clear(); + } + + public bool Contains(T item) { + return items.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) { + items.CopyTo(array, arrayIndex); + } + + public int Count { + get { return items.Count; } + } + + public bool IsReadOnly { + get { return readOnly; } + } + + public bool Remove(T item) { + ValidateModification(); + return items.Remove(item); + } + + public IEnumerator<T> GetEnumerator() { + return items.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + private void ValidateModification() { + if (readOnly) { + throw new NotSupportedException("List is read-only"); + } + } + } +} diff --git a/src/ProtocolBuffers/Collections/ReadOnlyDictionary.cs b/src/ProtocolBuffers/Collections/ReadOnlyDictionary.cs new file mode 100644 index 00000000..cd4b1898 --- /dev/null +++ b/src/ProtocolBuffers/Collections/ReadOnlyDictionary.cs @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Google.ProtocolBuffers.Collections { + /// <summary> + /// Read-only wrapper around another dictionary. + /// </summary> + public sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue> { + readonly IDictionary<TKey, TValue> wrapped; + + public ReadOnlyDictionary(IDictionary<TKey, TValue> wrapped) { + this.wrapped = wrapped; + } + + public void Add(TKey key, TValue value) { + throw new InvalidOperationException(); + } + + public bool ContainsKey(TKey key) { + return wrapped.ContainsKey(key); + } + + public ICollection<TKey> Keys { + get { return wrapped.Keys; } + } + + public bool Remove(TKey key) { + throw new InvalidOperationException(); + } + + public bool TryGetValue(TKey key, out TValue value) { + return wrapped.TryGetValue(key, out value); + } + + public ICollection<TValue> Values { + get { return wrapped.Values; } + } + + public TValue this[TKey key] { + get { + return wrapped[key]; + } + set { + throw new InvalidOperationException(); + } + } + + public void Add(KeyValuePair<TKey, TValue> item) { + throw new InvalidOperationException(); + } + + public void Clear() { + throw new InvalidOperationException(); + } + + public bool Contains(KeyValuePair<TKey, TValue> item) { + return wrapped.Contains(item); + } + + public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { + wrapped.CopyTo(array, arrayIndex); + } + + public int Count { + get { return wrapped.Count; } + } + + public bool IsReadOnly { + get { return true; } + } + + public bool Remove(KeyValuePair<TKey, TValue> item) { + throw new InvalidOperationException(); + } + + public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { + return wrapped.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return ((IEnumerable) wrapped).GetEnumerator(); + } + + public override bool Equals(object obj) { + return wrapped.Equals(obj); + } + + public override int GetHashCode() { + return wrapped.GetHashCode(); + } + + public override string ToString() { + return wrapped.ToString(); + } + } +} diff --git a/src/ProtocolBuffers/Delegates.cs b/src/ProtocolBuffers/Delegates.cs new file mode 100644 index 00000000..08774019 --- /dev/null +++ b/src/ProtocolBuffers/Delegates.cs @@ -0,0 +1,32 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.IO; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Delegate to return a stream when asked, used by MessageStreamIterator. + /// </summary> + public delegate Stream StreamProvider(); + + // These delegate declarations mirror the ones in .NET 3.5 for the sake of familiarity. + internal delegate TResult Func<TResult>(); + internal delegate TResult Func<T, TResult>(T arg); + internal delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); + internal delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3); + internal delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4); + internal delegate void Action(); + internal delegate void Action<T1, T2>(T1 arg1, T2 arg2); +} diff --git a/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs new file mode 100644 index 00000000..14d6bb64 --- /dev/null +++ b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs @@ -0,0 +1,49 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +using pb = global::Google.ProtocolBuffers; +using pbc = global::Google.ProtocolBuffers.Collections; +using pbd = global::Google.ProtocolBuffers.Descriptors; +using scg = global::System.Collections.Generic; +namespace Google.ProtocolBuffers.DescriptorProtos { + + public static partial class CSharpOptions { + + #region Descriptor + public static pbd::FileDescriptor Descriptor { + get { return descriptor; } + } + private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom( + global::System.Convert.FromBase64String( + "CiRnb29nbGUvcHJvdG9idWYvY3NoYXJwX29wdGlvbnMucHJvdG8SD2dvb2ds" + + "ZS5wcm90b2J1ZhogZ29vZ2xlL3Byb3RvYnVmL2Rlc2NyaXB0b3IucHJvdG86" + + "NwoPQ1NoYXJwTmFtZXNwYWNlEhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRp" + + "b25zGKCcASABKAk6PwoXQ1NoYXJwVW1icmVsbGFDbGFzc25hbWUSHC5nb29n" + + "bGUucHJvdG9idWYuRmlsZU9wdGlvbnMYoZwBIAEoCTo7ChNDU2hhcnBNdWx0" + + "aXBsZUZpbGVzEhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGKKcASAB" + + "KAg6OQoRQ1NoYXJwTmVzdENsYXNzZXMSHC5nb29nbGUucHJvdG9idWYuRmls" + + "ZU9wdGlvbnMYo5wBIAEoCDo7ChNDU2hhcnBQdWJsaWNDbGFzc2VzEhwuZ29v" + + "Z2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGKScASABKAhCPILiCSdHb29nbGUu" + + "UHJvdG9jb2xCdWZmZXJzLkRlc2NyaXB0b3JQcm90b3OK4gkNQ1NoYXJwT3B0" + + "aW9ucw=="), + new pbd::FileDescriptor[] { + global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor, + }); + #endregion + + #region Extensions + public static readonly pb::GeneratedExtensionBase<string> CSharpNamespace = + pb::GeneratedSingleExtension<string>.CreateInstance(Descriptor.Extensions[0]); + public static readonly pb::GeneratedExtensionBase<string> CSharpUmbrellaClassname = + pb::GeneratedSingleExtension<string>.CreateInstance(Descriptor.Extensions[1]); + public static readonly pb::GeneratedExtensionBase<bool> CSharpMultipleFiles = + pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[2]); + public static readonly pb::GeneratedExtensionBase<bool> CSharpNestClasses = + pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[3]); + public static readonly pb::GeneratedExtensionBase<bool> CSharpPublicClasses = + pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[4]); + #endregion + + #region Static variables + #endregion + } +} diff --git a/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs new file mode 100644 index 00000000..4e3c6572 --- /dev/null +++ b/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs @@ -0,0 +1,6131 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +using pb = global::Google.ProtocolBuffers; +using pbc = global::Google.ProtocolBuffers.Collections; +using pbd = global::Google.ProtocolBuffers.Descriptors; +using scg = global::System.Collections.Generic; +namespace Google.ProtocolBuffers.DescriptorProtos { + + public static partial class DescriptorProtoFile { + + #region Descriptor + public static pbd::FileDescriptor Descriptor { + get { return descriptor; } + } + private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom( + global::System.Convert.FromBase64String( + "CiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bxIPZ29vZ2xlLnBy" + + "b3RvYnVmIkcKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n" + + "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLcAgoTRmlsZURl" + + "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg8KB3BhY2thZ2UYAiABKAkS" + + "EgoKZGVwZW5kZW5jeRgDIAMoCRI2CgxtZXNzYWdlX3R5cGUYBCADKAsyIC5n" + + "b29nbGUucHJvdG9idWYuRGVzY3JpcHRvclByb3RvEjcKCWVudW1fdHlwZRgF" + + "IAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5FbnVtRGVzY3JpcHRvclByb3RvEjgK" + + "B3NlcnZpY2UYBiADKAsyJy5nb29nbGUucHJvdG9idWYuU2VydmljZURlc2Ny" + + "aXB0b3JQcm90bxI4CglleHRlbnNpb24YByADKAsyJS5nb29nbGUucHJvdG9i" + + "dWYuRmllbGREZXNjcmlwdG9yUHJvdG8SLQoHb3B0aW9ucxgIIAEoCzIcLmdv" + + "b2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9ucyKpAwoPRGVzY3JpcHRvclByb3Rv" + + "EgwKBG5hbWUYASABKAkSNAoFZmllbGQYAiADKAsyJS5nb29nbGUucHJvdG9i" + + "dWYuRmllbGREZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9uGAYgAygLMiUu" + + "Z29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEjUKC25lc3Rl" + + "ZF90eXBlGAMgAygLMiAuZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JQcm90" + + "bxI3CgllbnVtX3R5cGUYBCADKAsyJC5nb29nbGUucHJvdG9idWYuRW51bURl" + + "c2NyaXB0b3JQcm90bxJICg9leHRlbnNpb25fcmFuZ2UYBSADKAsyLy5nb29n" + + "bGUucHJvdG9idWYuRGVzY3JpcHRvclByb3RvLkV4dGVuc2lvblJhbmdlEjAK" + + "B29wdGlvbnMYByABKAsyHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlv" + + "bnMaLAoORXh0ZW5zaW9uUmFuZ2USDQoFc3RhcnQYASABKAUSCwoDZW5kGAIg" + + "ASgFIpQFChRGaWVsZERlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg4K" + + "Bm51bWJlchgDIAEoBRI6CgVsYWJlbBgEIAEoDjIrLmdvb2dsZS5wcm90b2J1" + + "Zi5GaWVsZERlc2NyaXB0b3JQcm90by5MYWJlbBI4CgR0eXBlGAUgASgOMiou" + + "Z29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLlR5cGUSEQoJ" + + "dHlwZV9uYW1lGAYgASgJEhAKCGV4dGVuZGVlGAIgASgJEhUKDWRlZmF1bHRf" + + "dmFsdWUYByABKAkSLgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5wcm90b2J1" + + "Zi5GaWVsZE9wdGlvbnMitgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQARIOCgpU" + + "WVBFX0ZMT0FUEAISDgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0EAQS" + + "DgoKVFlQRV9JTlQzMhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVfRklY" + + "RUQzMhAHEg0KCVRZUEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoKVFlQ" + + "RV9HUk9VUBAKEhAKDFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQDBIP" + + "CgtUWVBFX1VJTlQzMhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJWEVE" + + "MzIQDxIRCg1UWVBFX1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIPCgtU" + + "WVBFX1NJTlQ2NBASIkMKBUxhYmVsEhIKDkxBQkVMX09QVElPTkFMEAESEgoO" + + "TEFCRUxfUkVRVUlSRUQQAhISCg5MQUJFTF9SRVBFQVRFRBADIowBChNFbnVt" + + "RGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSOAoFdmFsdWUYAiADKAsy" + + "KS5nb29nbGUucHJvdG9idWYuRW51bVZhbHVlRGVzY3JpcHRvclByb3RvEi0K" + + "B29wdGlvbnMYAyABKAsyHC5nb29nbGUucHJvdG9idWYuRW51bU9wdGlvbnMi" + + "bAoYRW51bVZhbHVlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoG" + + "bnVtYmVyGAIgASgFEjIKB29wdGlvbnMYAyABKAsyIS5nb29nbGUucHJvdG9i" + + "dWYuRW51bVZhbHVlT3B0aW9ucyKQAQoWU2VydmljZURlc2NyaXB0b3JQcm90" + + "bxIMCgRuYW1lGAEgASgJEjYKBm1ldGhvZBgCIAMoCzImLmdvb2dsZS5wcm90" + + "b2J1Zi5NZXRob2REZXNjcmlwdG9yUHJvdG8SMAoHb3B0aW9ucxgDIAEoCzIf" + + "Lmdvb2dsZS5wcm90b2J1Zi5TZXJ2aWNlT3B0aW9ucyJ/ChVNZXRob2REZXNj" + + "cmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJ" + + "EhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29n" + + "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucyKrAgoLRmlsZU9wdGlvbnMSFAoM" + + "amF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3NuYW1lGAgg" + + "ASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNlEkoKDG9w" + + "dGltaXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9u" + + "cy5PcHRpbWl6ZU1vZGU6CUNPREVfU0laRRJDChR1bmludGVycHJldGVkX29w" + + "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w" + + "dGlvbiIoCgxPcHRpbWl6ZU1vZGUSCQoFU1BFRUQQARINCglDT0RFX1NJWkUQ" + + "AioJCOgHEICAgIACIogBCg5NZXNzYWdlT3B0aW9ucxImChdtZXNzYWdlX3Nl" + + "dF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v" + + "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP" + + "cHRpb24qCQjoBxCAgICAAiLVAQoMRmllbGRPcHRpb25zEjIKBWN0eXBlGAEg" + + "ASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZRIcChRl" + + "eHBlcmltZW50YWxfbWFwX2tleRgJIAEoCRJDChR1bmludGVycHJldGVkX29w" + + "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w" + + "dGlvbiIjCgVDVHlwZRIICgRDT1JEEAESEAoMU1RSSU5HX1BJRUNFEAIqCQjo" + + "BxCAgICAAiJdCgtFbnVtT3B0aW9ucxJDChR1bmludGVycHJldGVkX29wdGlv" + + "bhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlv" + + "bioJCOgHEICAgIACImIKEEVudW1WYWx1ZU9wdGlvbnMSQwoUdW5pbnRlcnBy" + + "ZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJw" + + "cmV0ZWRPcHRpb24qCQjoBxCAgICAAiJgCg5TZXJ2aWNlT3B0aW9ucxJDChR1" + + "bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYu" + + "VW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACIl8KDU1ldGhvZE9wdGlv" + + "bnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy" + + "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKFAgoTVW5p" + + "bnRlcnByZXRlZE9wdGlvbhI7CgRuYW1lGAIgAygLMi0uZ29vZ2xlLnByb3Rv" + + "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24uTmFtZVBhcnQSGAoQaWRlbnRpZmll" + + "cl92YWx1ZRgDIAEoCRIaChJwb3NpdGl2ZV9pbnRfdmFsdWUYBCABKAQSGgoS" + + "bmVnYXRpdmVfaW50X3ZhbHVlGAUgASgDEhQKDGRvdWJsZV92YWx1ZRgGIAEo" + + "ARIUCgxzdHJpbmdfdmFsdWUYByABKAwaMwoITmFtZVBhcnQSEQoJbmFtZV9w" + + "YXJ0GAEgAigJEhQKDGlzX2V4dGVuc2lvbhgCIAIoCEIpChNjb20uZ29vZ2xl" + + "LnByb3RvYnVmQhBEZXNjcmlwdG9yUHJvdG9zSAE="), + new pbd::FileDescriptor[] { + }); + #endregion + + #region Static variables + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_FileDescriptorSet__Descriptor + = Descriptor.MessageTypes[0]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet, global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet.Builder> internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet, global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet.Builder>(internal__static_google_protobuf_FileDescriptorSet__Descriptor, + new string[] { "File", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_FileDescriptorProto__Descriptor + = Descriptor.MessageTypes[1]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.Builder> internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.Builder>(internal__static_google_protobuf_FileDescriptorProto__Descriptor, + new string[] { "Name", "Package", "Dependency", "MessageType", "EnumType", "Service", "Extension", "Options", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_DescriptorProto__Descriptor + = Descriptor.MessageTypes[2]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder> internal__static_google_protobuf_DescriptorProto__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder>(internal__static_google_protobuf_DescriptorProto__Descriptor, + new string[] { "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "Options", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor + = internal__static_google_protobuf_DescriptorProto__Descriptor.NestedTypes[0]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Builder> internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Builder>(internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor, + new string[] { "Start", "End", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_FieldDescriptorProto__Descriptor + = Descriptor.MessageTypes[3]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder> internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder>(internal__static_google_protobuf_FieldDescriptorProto__Descriptor, + new string[] { "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "Options", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_EnumDescriptorProto__Descriptor + = Descriptor.MessageTypes[4]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder> internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder>(internal__static_google_protobuf_EnumDescriptorProto__Descriptor, + new string[] { "Name", "Value", "Options", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_EnumValueDescriptorProto__Descriptor + = Descriptor.MessageTypes[5]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.Builder> internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.Builder>(internal__static_google_protobuf_EnumValueDescriptorProto__Descriptor, + new string[] { "Name", "Number", "Options", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_ServiceDescriptorProto__Descriptor + = Descriptor.MessageTypes[6]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.Builder> internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.Builder>(internal__static_google_protobuf_ServiceDescriptorProto__Descriptor, + new string[] { "Name", "Method", "Options", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_MethodDescriptorProto__Descriptor + = Descriptor.MessageTypes[7]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.Builder> internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto, global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.Builder>(internal__static_google_protobuf_MethodDescriptorProto__Descriptor, + new string[] { "Name", "InputType", "OutputType", "Options", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_FileOptions__Descriptor + = Descriptor.MessageTypes[8]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FileOptions, global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Builder> internal__static_google_protobuf_FileOptions__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FileOptions, global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Builder>(internal__static_google_protobuf_FileOptions__Descriptor, + new string[] { "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "OptimizeFor", "UninterpretedOption", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_MessageOptions__Descriptor + = Descriptor.MessageTypes[9]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions, global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.Builder> internal__static_google_protobuf_MessageOptions__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions, global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.Builder>(internal__static_google_protobuf_MessageOptions__Descriptor, + new string[] { "MessageSetWireFormat", "UninterpretedOption", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_FieldOptions__Descriptor + = Descriptor.MessageTypes[10]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions, global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Builder> internal__static_google_protobuf_FieldOptions__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions, global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Builder>(internal__static_google_protobuf_FieldOptions__Descriptor, + new string[] { "Ctype", "ExperimentalMapKey", "UninterpretedOption", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_EnumOptions__Descriptor + = Descriptor.MessageTypes[11]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions, global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.Builder> internal__static_google_protobuf_EnumOptions__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions, global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.Builder>(internal__static_google_protobuf_EnumOptions__Descriptor, + new string[] { "UninterpretedOption", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_EnumValueOptions__Descriptor + = Descriptor.MessageTypes[12]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions, global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.Builder> internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions, global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.Builder>(internal__static_google_protobuf_EnumValueOptions__Descriptor, + new string[] { "UninterpretedOption", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_ServiceOptions__Descriptor + = Descriptor.MessageTypes[13]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions, global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.Builder> internal__static_google_protobuf_ServiceOptions__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions, global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.Builder>(internal__static_google_protobuf_ServiceOptions__Descriptor, + new string[] { "UninterpretedOption", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_MethodOptions__Descriptor + = Descriptor.MessageTypes[14]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions, global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.Builder> internal__static_google_protobuf_MethodOptions__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions, global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.Builder>(internal__static_google_protobuf_MethodOptions__Descriptor, + new string[] { "UninterpretedOption", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_UninterpretedOption__Descriptor + = Descriptor.MessageTypes[15]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder> internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder>(internal__static_google_protobuf_UninterpretedOption__Descriptor, + new string[] { "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", }); + internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_UninterpretedOption_NamePart__Descriptor + = internal__static_google_protobuf_UninterpretedOption__Descriptor.NestedTypes[0]; + internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.Builder> internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable + = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.Builder>(internal__static_google_protobuf_UninterpretedOption_NamePart__Descriptor, + new string[] { "NamePart", "IsExtension", }); + #endregion + } + #region Messages + public sealed partial class FileDescriptorSet : pb::GeneratedMessage<FileDescriptorSet, FileDescriptorSet.Builder> { + private static readonly FileDescriptorSet defaultInstance = new Builder().BuildPartial(); + public static FileDescriptorSet DefaultInstance { + get { return defaultInstance; } + } + + public override FileDescriptorSet DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override FileDescriptorSet ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorSet__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<FileDescriptorSet, FileDescriptorSet.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> file_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> FileList { + get { return file_; } + } + public int FileCount { + get { return file_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto GetFile(int index) { + return file_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto element in FileList) { + if (!element.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto element in FileList) { + output.WriteMessage(1, element); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto element in FileList) { + size += pb::CodedOutputStream.ComputeMessageSize(1, element); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static FileDescriptorSet ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FileDescriptorSet ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FileDescriptorSet ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FileDescriptorSet ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FileDescriptorSet ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FileDescriptorSet ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static FileDescriptorSet ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FileDescriptorSet ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(FileDescriptorSet prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<FileDescriptorSet, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + FileDescriptorSet result = new FileDescriptorSet(); + + protected override FileDescriptorSet MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new FileDescriptorSet(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return FileDescriptorSet.Descriptor; } + } + + public override FileDescriptorSet DefaultInstanceForType { + get { return FileDescriptorSet.DefaultInstance; } + } + + public override FileDescriptorSet BuildPartial() { + result.file_.MakeReadOnly(); + FileDescriptorSet returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is FileDescriptorSet) { + return MergeFrom((FileDescriptorSet) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(FileDescriptorSet other) { + if (other == FileDescriptorSet.DefaultInstance) return this; + if (other.file_.Count != 0) { + base.AddRange(other.file_, result.file_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddFile(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> FileList { + get { return result.file_; } + } + public int FileCount { + get { return result.FileCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto GetFile(int index) { + return result.GetFile(index); + } + public Builder SetFile(int index, global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto value) { + result.file_[index] = value; + return this; + } + public Builder SetFile(int index, global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.Builder builderForValue) { + result.file_[index] = builderForValue.Build(); + return this; + } + public Builder AddFile(global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto value) { + result.file_.Add(value); + return this; + } + public Builder AddFile(global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.Builder builderForValue) { + result.file_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeFile(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> values) { + base.AddRange(values, result.file_); + return this; + } + public Builder ClearFile() { + result.file_.Clear(); + return this; + } + } + } + + public sealed partial class FileDescriptorProto : pb::GeneratedMessage<FileDescriptorProto, FileDescriptorProto.Builder> { + private static readonly FileDescriptorProto defaultInstance = new Builder().BuildPartial(); + public static FileDescriptorProto DefaultInstance { + get { return defaultInstance; } + } + + public override FileDescriptorProto DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override FileDescriptorProto ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorProto__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<FileDescriptorProto, FileDescriptorProto.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable; } + } + + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + private bool hasPackage; + private string package_ = ""; + public bool HasPackage { + get { return hasPackage; } + } + public string Package { + get { return package_; } + } + + private pbc::PopsicleList<string> dependency_ = new pbc::PopsicleList<string>(); + public scg::IList<string> DependencyList { + get { return pbc::Lists.AsReadOnly(dependency_); } + } + public int DependencyCount { + get { return dependency_.Count; } + } + public string GetDependency(int index) { + return dependency_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> messageType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> MessageTypeList { + get { return messageType_; } + } + public int MessageTypeCount { + get { return messageType_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto GetMessageType(int index) { + return messageType_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList { + get { return enumType_; } + } + public int EnumTypeCount { + get { return enumType_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto GetEnumType(int index) { + return enumType_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> service_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> ServiceList { + get { return service_; } + } + public int ServiceCount { + get { return service_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto GetService(int index) { + return service_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList { + get { return extension_; } + } + public int ExtensionCount { + get { return extension_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto GetExtension(int index) { + return extension_[index]; + } + + private bool hasOptions; + private global::Google.ProtocolBuffers.DescriptorProtos.FileOptions options_ = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.DefaultInstance; + public bool HasOptions { + get { return hasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FileOptions Options { + get { return options_; } + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto element in MessageTypeList) { + if (!element.IsInitialized) return false; + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto element in EnumTypeList) { + if (!element.IsInitialized) return false; + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto element in ServiceList) { + if (!element.IsInitialized) return false; + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in ExtensionList) { + if (!element.IsInitialized) return false; + } + if (HasOptions) { + if (!Options.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasName) { + output.WriteString(1, Name); + } + if (HasPackage) { + output.WriteString(2, Package); + } + foreach (string element in DependencyList) { + output.WriteString(3, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto element in MessageTypeList) { + output.WriteMessage(4, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto element in EnumTypeList) { + output.WriteMessage(5, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto element in ServiceList) { + output.WriteMessage(6, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in ExtensionList) { + output.WriteMessage(7, element); + } + if (HasOptions) { + output.WriteMessage(8, Options); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + if (HasPackage) { + size += pb::CodedOutputStream.ComputeStringSize(2, Package); + } + foreach (string element in DependencyList) { + size += pb::CodedOutputStream.ComputeStringSize(3, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto element in MessageTypeList) { + size += pb::CodedOutputStream.ComputeMessageSize(4, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto element in EnumTypeList) { + size += pb::CodedOutputStream.ComputeMessageSize(5, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto element in ServiceList) { + size += pb::CodedOutputStream.ComputeMessageSize(6, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in ExtensionList) { + size += pb::CodedOutputStream.ComputeMessageSize(7, element); + } + if (HasOptions) { + size += pb::CodedOutputStream.ComputeMessageSize(8, Options); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static FileDescriptorProto ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FileDescriptorProto ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FileDescriptorProto ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FileDescriptorProto ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FileDescriptorProto ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FileDescriptorProto ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static FileDescriptorProto ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FileDescriptorProto ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(FileDescriptorProto prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<FileDescriptorProto, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + FileDescriptorProto result = new FileDescriptorProto(); + + protected override FileDescriptorProto MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new FileDescriptorProto(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return FileDescriptorProto.Descriptor; } + } + + public override FileDescriptorProto DefaultInstanceForType { + get { return FileDescriptorProto.DefaultInstance; } + } + + public override FileDescriptorProto BuildPartial() { + result.dependency_.MakeReadOnly(); + result.messageType_.MakeReadOnly(); + result.enumType_.MakeReadOnly(); + result.service_.MakeReadOnly(); + result.extension_.MakeReadOnly(); + FileDescriptorProto returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is FileDescriptorProto) { + return MergeFrom((FileDescriptorProto) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(FileDescriptorProto other) { + if (other == FileDescriptorProto.DefaultInstance) return this; + if (other.HasName) { + Name = other.Name; + } + if (other.HasPackage) { + Package = other.Package; + } + if (other.dependency_.Count != 0) { + base.AddRange(other.dependency_, result.dependency_); + } + if (other.messageType_.Count != 0) { + base.AddRange(other.messageType_, result.messageType_); + } + if (other.enumType_.Count != 0) { + base.AddRange(other.enumType_, result.enumType_); + } + if (other.service_.Count != 0) { + base.AddRange(other.service_, result.service_); + } + if (other.extension_.Count != 0) { + base.AddRange(other.extension_, result.extension_); + } + if (other.HasOptions) { + MergeOptions(other.Options); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + Package = input.ReadString(); + break; + } + case 26: { + AddDependency(input.ReadString()); + break; + } + case 34: { + global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddMessageType(subBuilder.BuildPartial()); + break; + } + case 42: { + global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddEnumType(subBuilder.BuildPartial()); + break; + } + case 50: { + global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddService(subBuilder.BuildPartial()); + break; + } + case 58: { + global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddExtension(subBuilder.BuildPartial()); + break; + } + case 66: { + global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.CreateBuilder(); + if (HasOptions) { + subBuilder.MergeFrom(Options); + } + input.ReadMessage(subBuilder, extensionRegistry); + Options = subBuilder.BuildPartial(); + break; + } + } + } + } + + + public bool HasName { + get { return result.HasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + result.hasName = false; + result.name_ = ""; + return this; + } + + public bool HasPackage { + get { return result.HasPackage; } + } + public string Package { + get { return result.Package; } + set { SetPackage(value); } + } + public Builder SetPackage(string value) { + result.hasPackage = true; + result.package_ = value; + return this; + } + public Builder ClearPackage() { + result.hasPackage = false; + result.package_ = ""; + return this; + } + + public scg::IList<string> DependencyList { + get { return result.dependency_; } + } + public int DependencyCount { + get { return result.DependencyCount; } + } + public string GetDependency(int index) { + return result.GetDependency(index); + } + public Builder SetDependency(int index, string value) { + result.dependency_[index] = value; + return this; + } + public Builder AddDependency(string value) { + result.dependency_.Add(value); + return this; + } + public Builder AddRangeDependency(scg::IEnumerable<string> values) { + base.AddRange(values, result.dependency_); + return this; + } + public Builder ClearDependency() { + result.dependency_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> MessageTypeList { + get { return result.messageType_; } + } + public int MessageTypeCount { + get { return result.MessageTypeCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto GetMessageType(int index) { + return result.GetMessageType(index); + } + public Builder SetMessageType(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto value) { + result.messageType_[index] = value; + return this; + } + public Builder SetMessageType(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder builderForValue) { + result.messageType_[index] = builderForValue.Build(); + return this; + } + public Builder AddMessageType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto value) { + result.messageType_.Add(value); + return this; + } + public Builder AddMessageType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder builderForValue) { + result.messageType_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeMessageType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> values) { + base.AddRange(values, result.messageType_); + return this; + } + public Builder ClearMessageType() { + result.messageType_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList { + get { return result.enumType_; } + } + public int EnumTypeCount { + get { return result.EnumTypeCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto GetEnumType(int index) { + return result.GetEnumType(index); + } + public Builder SetEnumType(int index, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto value) { + result.enumType_[index] = value; + return this; + } + public Builder SetEnumType(int index, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + result.enumType_[index] = builderForValue.Build(); + return this; + } + public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto value) { + result.enumType_.Add(value); + return this; + } + public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + result.enumType_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeEnumType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> values) { + base.AddRange(values, result.enumType_); + return this; + } + public Builder ClearEnumType() { + result.enumType_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> ServiceList { + get { return result.service_; } + } + public int ServiceCount { + get { return result.ServiceCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto GetService(int index) { + return result.GetService(index); + } + public Builder SetService(int index, global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto value) { + result.service_[index] = value; + return this; + } + public Builder SetService(int index, global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) { + result.service_[index] = builderForValue.Build(); + return this; + } + public Builder AddService(global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto value) { + result.service_.Add(value); + return this; + } + public Builder AddService(global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) { + result.service_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeService(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> values) { + base.AddRange(values, result.service_); + return this; + } + public Builder ClearService() { + result.service_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList { + get { return result.extension_; } + } + public int ExtensionCount { + get { return result.ExtensionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto GetExtension(int index) { + return result.GetExtension(index); + } + public Builder SetExtension(int index, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) { + result.extension_[index] = value; + return this; + } + public Builder SetExtension(int index, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.extension_[index] = builderForValue.Build(); + return this; + } + public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) { + result.extension_.Add(value); + return this; + } + public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.extension_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeExtension(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> values) { + base.AddRange(values, result.extension_); + return this; + } + public Builder ClearExtension() { + result.extension_.Clear(); + return this; + } + + public bool HasOptions { + get { return result.HasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FileOptions Options { + get { return result.Options; } + set { SetOptions(value); } + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions value) { + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.Build(); + return this; + } + public Builder MergeOptions(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions value) { + if (result.HasOptions && + result.options_ != global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.DefaultInstance) { + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.CreateBuilder(result.options_).MergeFrom(value).BuildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder ClearOptions() { + result.hasOptions = false; + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.DefaultInstance; + return this; + } + } + } + + public sealed partial class DescriptorProto : pb::GeneratedMessage<DescriptorProto, DescriptorProto.Builder> { + private static readonly DescriptorProto defaultInstance = new Builder().BuildPartial(); + public static DescriptorProto DefaultInstance { + get { return defaultInstance; } + } + + public override DescriptorProto DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override DescriptorProto ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<DescriptorProto, DescriptorProto.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto__FieldAccessorTable; } + } + + #region Nested types + public static class Types { + public sealed partial class ExtensionRange : pb::GeneratedMessage<ExtensionRange, ExtensionRange.Builder> { + private static readonly ExtensionRange defaultInstance = new Builder().BuildPartial(); + public static ExtensionRange DefaultInstance { + get { return defaultInstance; } + } + + public override ExtensionRange DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override ExtensionRange ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<ExtensionRange, ExtensionRange.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable; } + } + + private bool hasStart; + private int start_ = 0; + public bool HasStart { + get { return hasStart; } + } + public int Start { + get { return start_; } + } + + private bool hasEnd; + private int end_ = 0; + public bool HasEnd { + get { return hasEnd; } + } + public int End { + get { return end_; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasStart) { + output.WriteInt32(1, Start); + } + if (HasEnd) { + output.WriteInt32(2, End); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasStart) { + size += pb::CodedOutputStream.ComputeInt32Size(1, Start); + } + if (HasEnd) { + size += pb::CodedOutputStream.ComputeInt32Size(2, End); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static ExtensionRange ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ExtensionRange ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ExtensionRange ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ExtensionRange ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ExtensionRange ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ExtensionRange ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static ExtensionRange ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ExtensionRange ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(ExtensionRange prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<ExtensionRange, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + ExtensionRange result = new ExtensionRange(); + + protected override ExtensionRange MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new ExtensionRange(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return ExtensionRange.Descriptor; } + } + + public override ExtensionRange DefaultInstanceForType { + get { return ExtensionRange.DefaultInstance; } + } + + public override ExtensionRange BuildPartial() { + ExtensionRange returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is ExtensionRange) { + return MergeFrom((ExtensionRange) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(ExtensionRange other) { + if (other == ExtensionRange.DefaultInstance) return this; + if (other.HasStart) { + Start = other.Start; + } + if (other.HasEnd) { + End = other.End; + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 8: { + Start = input.ReadInt32(); + break; + } + case 16: { + End = input.ReadInt32(); + break; + } + } + } + } + + + public bool HasStart { + get { return result.HasStart; } + } + public int Start { + get { return result.Start; } + set { SetStart(value); } + } + public Builder SetStart(int value) { + result.hasStart = true; + result.start_ = value; + return this; + } + public Builder ClearStart() { + result.hasStart = false; + result.start_ = 0; + return this; + } + + public bool HasEnd { + get { return result.HasEnd; } + } + public int End { + get { return result.End; } + set { SetEnd(value); } + } + public Builder SetEnd(int value) { + result.hasEnd = true; + result.end_ = value; + return this; + } + public Builder ClearEnd() { + result.hasEnd = false; + result.end_ = 0; + return this; + } + } + } + + } + #endregion + + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> field_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> FieldList { + get { return field_; } + } + public int FieldCount { + get { return field_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto GetField(int index) { + return field_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList { + get { return extension_; } + } + public int ExtensionCount { + get { return extension_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto GetExtension(int index) { + return extension_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> nestedType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> NestedTypeList { + get { return nestedType_; } + } + public int NestedTypeCount { + get { return nestedType_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto GetNestedType(int index) { + return nestedType_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList { + get { return enumType_; } + } + public int EnumTypeCount { + get { return enumType_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto GetEnumType(int index) { + return enumType_[index]; + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> extensionRange_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> ExtensionRangeList { + get { return extensionRange_; } + } + public int ExtensionRangeCount { + get { return extensionRange_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange GetExtensionRange(int index) { + return extensionRange_[index]; + } + + private bool hasOptions; + private global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions options_ = global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.DefaultInstance; + public bool HasOptions { + get { return hasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions Options { + get { return options_; } + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in FieldList) { + if (!element.IsInitialized) return false; + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in ExtensionList) { + if (!element.IsInitialized) return false; + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto element in NestedTypeList) { + if (!element.IsInitialized) return false; + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto element in EnumTypeList) { + if (!element.IsInitialized) return false; + } + if (HasOptions) { + if (!Options.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasName) { + output.WriteString(1, Name); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in FieldList) { + output.WriteMessage(2, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto element in NestedTypeList) { + output.WriteMessage(3, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto element in EnumTypeList) { + output.WriteMessage(4, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange element in ExtensionRangeList) { + output.WriteMessage(5, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in ExtensionList) { + output.WriteMessage(6, element); + } + if (HasOptions) { + output.WriteMessage(7, Options); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in FieldList) { + size += pb::CodedOutputStream.ComputeMessageSize(2, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in ExtensionList) { + size += pb::CodedOutputStream.ComputeMessageSize(6, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto element in NestedTypeList) { + size += pb::CodedOutputStream.ComputeMessageSize(3, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto element in EnumTypeList) { + size += pb::CodedOutputStream.ComputeMessageSize(4, element); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange element in ExtensionRangeList) { + size += pb::CodedOutputStream.ComputeMessageSize(5, element); + } + if (HasOptions) { + size += pb::CodedOutputStream.ComputeMessageSize(7, Options); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static DescriptorProto ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static DescriptorProto ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static DescriptorProto ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static DescriptorProto ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static DescriptorProto ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static DescriptorProto ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static DescriptorProto ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static DescriptorProto ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(DescriptorProto prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<DescriptorProto, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + DescriptorProto result = new DescriptorProto(); + + protected override DescriptorProto MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new DescriptorProto(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return DescriptorProto.Descriptor; } + } + + public override DescriptorProto DefaultInstanceForType { + get { return DescriptorProto.DefaultInstance; } + } + + public override DescriptorProto BuildPartial() { + result.field_.MakeReadOnly(); + result.extension_.MakeReadOnly(); + result.nestedType_.MakeReadOnly(); + result.enumType_.MakeReadOnly(); + result.extensionRange_.MakeReadOnly(); + DescriptorProto returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is DescriptorProto) { + return MergeFrom((DescriptorProto) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(DescriptorProto other) { + if (other == DescriptorProto.DefaultInstance) return this; + if (other.HasName) { + Name = other.Name; + } + if (other.field_.Count != 0) { + base.AddRange(other.field_, result.field_); + } + if (other.extension_.Count != 0) { + base.AddRange(other.extension_, result.extension_); + } + if (other.nestedType_.Count != 0) { + base.AddRange(other.nestedType_, result.nestedType_); + } + if (other.enumType_.Count != 0) { + base.AddRange(other.enumType_, result.enumType_); + } + if (other.extensionRange_.Count != 0) { + base.AddRange(other.extensionRange_, result.extensionRange_); + } + if (other.HasOptions) { + MergeOptions(other.Options); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddField(subBuilder.BuildPartial()); + break; + } + case 26: { + global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddNestedType(subBuilder.BuildPartial()); + break; + } + case 34: { + global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddEnumType(subBuilder.BuildPartial()); + break; + } + case 42: { + global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddExtensionRange(subBuilder.BuildPartial()); + break; + } + case 50: { + global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddExtension(subBuilder.BuildPartial()); + break; + } + case 58: { + global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.CreateBuilder(); + if (HasOptions) { + subBuilder.MergeFrom(Options); + } + input.ReadMessage(subBuilder, extensionRegistry); + Options = subBuilder.BuildPartial(); + break; + } + } + } + } + + + public bool HasName { + get { return result.HasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + result.hasName = false; + result.name_ = ""; + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> FieldList { + get { return result.field_; } + } + public int FieldCount { + get { return result.FieldCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto GetField(int index) { + return result.GetField(index); + } + public Builder SetField(int index, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) { + result.field_[index] = value; + return this; + } + public Builder SetField(int index, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.field_[index] = builderForValue.Build(); + return this; + } + public Builder AddField(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) { + result.field_.Add(value); + return this; + } + public Builder AddField(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.field_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeField(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> values) { + base.AddRange(values, result.field_); + return this; + } + public Builder ClearField() { + result.field_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList { + get { return result.extension_; } + } + public int ExtensionCount { + get { return result.ExtensionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto GetExtension(int index) { + return result.GetExtension(index); + } + public Builder SetExtension(int index, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) { + result.extension_[index] = value; + return this; + } + public Builder SetExtension(int index, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.extension_[index] = builderForValue.Build(); + return this; + } + public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) { + result.extension_.Add(value); + return this; + } + public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.extension_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeExtension(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> values) { + base.AddRange(values, result.extension_); + return this; + } + public Builder ClearExtension() { + result.extension_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> NestedTypeList { + get { return result.nestedType_; } + } + public int NestedTypeCount { + get { return result.NestedTypeCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto GetNestedType(int index) { + return result.GetNestedType(index); + } + public Builder SetNestedType(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto value) { + result.nestedType_[index] = value; + return this; + } + public Builder SetNestedType(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder builderForValue) { + result.nestedType_[index] = builderForValue.Build(); + return this; + } + public Builder AddNestedType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto value) { + result.nestedType_.Add(value); + return this; + } + public Builder AddNestedType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder builderForValue) { + result.nestedType_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeNestedType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> values) { + base.AddRange(values, result.nestedType_); + return this; + } + public Builder ClearNestedType() { + result.nestedType_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList { + get { return result.enumType_; } + } + public int EnumTypeCount { + get { return result.EnumTypeCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto GetEnumType(int index) { + return result.GetEnumType(index); + } + public Builder SetEnumType(int index, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto value) { + result.enumType_[index] = value; + return this; + } + public Builder SetEnumType(int index, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + result.enumType_[index] = builderForValue.Build(); + return this; + } + public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto value) { + result.enumType_.Add(value); + return this; + } + public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + result.enumType_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeEnumType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> values) { + base.AddRange(values, result.enumType_); + return this; + } + public Builder ClearEnumType() { + result.enumType_.Clear(); + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> ExtensionRangeList { + get { return result.extensionRange_; } + } + public int ExtensionRangeCount { + get { return result.ExtensionRangeCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange GetExtensionRange(int index) { + return result.GetExtensionRange(index); + } + public Builder SetExtensionRange(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange value) { + result.extensionRange_[index] = value; + return this; + } + public Builder SetExtensionRange(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Builder builderForValue) { + result.extensionRange_[index] = builderForValue.Build(); + return this; + } + public Builder AddExtensionRange(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange value) { + result.extensionRange_.Add(value); + return this; + } + public Builder AddExtensionRange(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Builder builderForValue) { + result.extensionRange_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeExtensionRange(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> values) { + base.AddRange(values, result.extensionRange_); + return this; + } + public Builder ClearExtensionRange() { + result.extensionRange_.Clear(); + return this; + } + + public bool HasOptions { + get { return result.HasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions Options { + get { return result.Options; } + set { SetOptions(value); } + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions value) { + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.Build(); + return this; + } + public Builder MergeOptions(global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions value) { + if (result.HasOptions && + result.options_ != global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.DefaultInstance) { + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.CreateBuilder(result.options_).MergeFrom(value).BuildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder ClearOptions() { + result.hasOptions = false; + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.DefaultInstance; + return this; + } + } + } + + public sealed partial class FieldDescriptorProto : pb::GeneratedMessage<FieldDescriptorProto, FieldDescriptorProto.Builder> { + private static readonly FieldDescriptorProto defaultInstance = new Builder().BuildPartial(); + public static FieldDescriptorProto DefaultInstance { + get { return defaultInstance; } + } + + public override FieldDescriptorProto DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override FieldDescriptorProto ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldDescriptorProto__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<FieldDescriptorProto, FieldDescriptorProto.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable; } + } + + #region Nested types + public static class Types { + public enum Type { + TYPE_DOUBLE = 1, + TYPE_FLOAT = 2, + TYPE_INT64 = 3, + TYPE_UINT64 = 4, + TYPE_INT32 = 5, + TYPE_FIXED64 = 6, + TYPE_FIXED32 = 7, + TYPE_BOOL = 8, + TYPE_STRING = 9, + TYPE_GROUP = 10, + TYPE_MESSAGE = 11, + TYPE_BYTES = 12, + TYPE_UINT32 = 13, + TYPE_ENUM = 14, + TYPE_SFIXED32 = 15, + TYPE_SFIXED64 = 16, + TYPE_SINT32 = 17, + TYPE_SINT64 = 18, + } + + public enum Label { + LABEL_OPTIONAL = 1, + LABEL_REQUIRED = 2, + LABEL_REPEATED = 3, + } + + } + #endregion + + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + private bool hasNumber; + private int number_ = 0; + public bool HasNumber { + get { return hasNumber; } + } + public int Number { + get { return number_; } + } + + private bool hasLabel; + private global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label label_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; + public bool HasLabel { + get { return hasLabel; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label Label { + get { return label_; } + } + + private bool hasType; + private global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type type_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE; + public bool HasType { + get { return hasType; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type Type { + get { return type_; } + } + + private bool hasTypeName; + private string typeName_ = ""; + public bool HasTypeName { + get { return hasTypeName; } + } + public string TypeName { + get { return typeName_; } + } + + private bool hasExtendee; + private string extendee_ = ""; + public bool HasExtendee { + get { return hasExtendee; } + } + public string Extendee { + get { return extendee_; } + } + + private bool hasDefaultValue; + private string defaultValue_ = ""; + public bool HasDefaultValue { + get { return hasDefaultValue; } + } + public string DefaultValue { + get { return defaultValue_; } + } + + private bool hasOptions; + private global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions options_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.DefaultInstance; + public bool HasOptions { + get { return hasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions Options { + get { return options_; } + } + + public override bool IsInitialized { + get { + if (HasOptions) { + if (!Options.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasName) { + output.WriteString(1, Name); + } + if (HasExtendee) { + output.WriteString(2, Extendee); + } + if (HasNumber) { + output.WriteInt32(3, Number); + } + if (HasLabel) { + output.WriteEnum(4, (int) Label); + } + if (HasType) { + output.WriteEnum(5, (int) Type); + } + if (HasTypeName) { + output.WriteString(6, TypeName); + } + if (HasDefaultValue) { + output.WriteString(7, DefaultValue); + } + if (HasOptions) { + output.WriteMessage(8, Options); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + if (HasNumber) { + size += pb::CodedOutputStream.ComputeInt32Size(3, Number); + } + if (HasLabel) { + size += pb::CodedOutputStream.ComputeEnumSize(4, (int) Label); + } + if (HasType) { + size += pb::CodedOutputStream.ComputeEnumSize(5, (int) Type); + } + if (HasTypeName) { + size += pb::CodedOutputStream.ComputeStringSize(6, TypeName); + } + if (HasExtendee) { + size += pb::CodedOutputStream.ComputeStringSize(2, Extendee); + } + if (HasDefaultValue) { + size += pb::CodedOutputStream.ComputeStringSize(7, DefaultValue); + } + if (HasOptions) { + size += pb::CodedOutputStream.ComputeMessageSize(8, Options); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static FieldDescriptorProto ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FieldDescriptorProto ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FieldDescriptorProto ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FieldDescriptorProto ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FieldDescriptorProto ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FieldDescriptorProto ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static FieldDescriptorProto ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FieldDescriptorProto ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(FieldDescriptorProto prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<FieldDescriptorProto, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + FieldDescriptorProto result = new FieldDescriptorProto(); + + protected override FieldDescriptorProto MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new FieldDescriptorProto(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return FieldDescriptorProto.Descriptor; } + } + + public override FieldDescriptorProto DefaultInstanceForType { + get { return FieldDescriptorProto.DefaultInstance; } + } + + public override FieldDescriptorProto BuildPartial() { + FieldDescriptorProto returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is FieldDescriptorProto) { + return MergeFrom((FieldDescriptorProto) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(FieldDescriptorProto other) { + if (other == FieldDescriptorProto.DefaultInstance) return this; + if (other.HasName) { + Name = other.Name; + } + if (other.HasNumber) { + Number = other.Number; + } + if (other.HasLabel) { + Label = other.Label; + } + if (other.HasType) { + Type = other.Type; + } + if (other.HasTypeName) { + TypeName = other.TypeName; + } + if (other.HasExtendee) { + Extendee = other.Extendee; + } + if (other.HasDefaultValue) { + DefaultValue = other.DefaultValue; + } + if (other.HasOptions) { + MergeOptions(other.Options); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + Extendee = input.ReadString(); + break; + } + case 24: { + Number = input.ReadInt32(); + break; + } + case 32: { + int rawValue = input.ReadEnum(); + if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label), rawValue)) { + unknownFields.MergeVarintField(4, (ulong) rawValue); + } else { + Label = (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label) rawValue; + } + break; + } + case 40: { + int rawValue = input.ReadEnum(); + if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type), rawValue)) { + unknownFields.MergeVarintField(5, (ulong) rawValue); + } else { + Type = (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type) rawValue; + } + break; + } + case 50: { + TypeName = input.ReadString(); + break; + } + case 58: { + DefaultValue = input.ReadString(); + break; + } + case 66: { + global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.CreateBuilder(); + if (HasOptions) { + subBuilder.MergeFrom(Options); + } + input.ReadMessage(subBuilder, extensionRegistry); + Options = subBuilder.BuildPartial(); + break; + } + } + } + } + + + public bool HasName { + get { return result.HasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + result.hasName = false; + result.name_ = ""; + return this; + } + + public bool HasNumber { + get { return result.HasNumber; } + } + public int Number { + get { return result.Number; } + set { SetNumber(value); } + } + public Builder SetNumber(int value) { + result.hasNumber = true; + result.number_ = value; + return this; + } + public Builder ClearNumber() { + result.hasNumber = false; + result.number_ = 0; + return this; + } + + public bool HasLabel { + get { return result.HasLabel; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label Label { + get { return result.Label; } + set { SetLabel(value); } + } + public Builder SetLabel(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label value) { + result.hasLabel = true; + result.label_ = value; + return this; + } + public Builder ClearLabel() { + result.hasLabel = false; + result.label_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; + return this; + } + + public bool HasType { + get { return result.HasType; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type Type { + get { return result.Type; } + set { SetType(value); } + } + public Builder SetType(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type value) { + result.hasType = true; + result.type_ = value; + return this; + } + public Builder ClearType() { + result.hasType = false; + result.type_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE; + return this; + } + + public bool HasTypeName { + get { return result.HasTypeName; } + } + public string TypeName { + get { return result.TypeName; } + set { SetTypeName(value); } + } + public Builder SetTypeName(string value) { + result.hasTypeName = true; + result.typeName_ = value; + return this; + } + public Builder ClearTypeName() { + result.hasTypeName = false; + result.typeName_ = ""; + return this; + } + + public bool HasExtendee { + get { return result.HasExtendee; } + } + public string Extendee { + get { return result.Extendee; } + set { SetExtendee(value); } + } + public Builder SetExtendee(string value) { + result.hasExtendee = true; + result.extendee_ = value; + return this; + } + public Builder ClearExtendee() { + result.hasExtendee = false; + result.extendee_ = ""; + return this; + } + + public bool HasDefaultValue { + get { return result.HasDefaultValue; } + } + public string DefaultValue { + get { return result.DefaultValue; } + set { SetDefaultValue(value); } + } + public Builder SetDefaultValue(string value) { + result.hasDefaultValue = true; + result.defaultValue_ = value; + return this; + } + public Builder ClearDefaultValue() { + result.hasDefaultValue = false; + result.defaultValue_ = ""; + return this; + } + + public bool HasOptions { + get { return result.HasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions Options { + get { return result.Options; } + set { SetOptions(value); } + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions value) { + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.Build(); + return this; + } + public Builder MergeOptions(global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions value) { + if (result.HasOptions && + result.options_ != global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.DefaultInstance) { + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.CreateBuilder(result.options_).MergeFrom(value).BuildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder ClearOptions() { + result.hasOptions = false; + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.DefaultInstance; + return this; + } + } + } + + public sealed partial class EnumDescriptorProto : pb::GeneratedMessage<EnumDescriptorProto, EnumDescriptorProto.Builder> { + private static readonly EnumDescriptorProto defaultInstance = new Builder().BuildPartial(); + public static EnumDescriptorProto DefaultInstance { + get { return defaultInstance; } + } + + public override EnumDescriptorProto DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override EnumDescriptorProto ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumDescriptorProto__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<EnumDescriptorProto, EnumDescriptorProto.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable; } + } + + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> value_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> ValueList { + get { return value_; } + } + public int ValueCount { + get { return value_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto GetValue(int index) { + return value_[index]; + } + + private bool hasOptions; + private global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions options_ = global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.DefaultInstance; + public bool HasOptions { + get { return hasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions Options { + get { return options_; } + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto element in ValueList) { + if (!element.IsInitialized) return false; + } + if (HasOptions) { + if (!Options.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasName) { + output.WriteString(1, Name); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto element in ValueList) { + output.WriteMessage(2, element); + } + if (HasOptions) { + output.WriteMessage(3, Options); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto element in ValueList) { + size += pb::CodedOutputStream.ComputeMessageSize(2, element); + } + if (HasOptions) { + size += pb::CodedOutputStream.ComputeMessageSize(3, Options); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static EnumDescriptorProto ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumDescriptorProto ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumDescriptorProto ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumDescriptorProto ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumDescriptorProto ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumDescriptorProto ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static EnumDescriptorProto ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumDescriptorProto ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(EnumDescriptorProto prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<EnumDescriptorProto, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + EnumDescriptorProto result = new EnumDescriptorProto(); + + protected override EnumDescriptorProto MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new EnumDescriptorProto(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return EnumDescriptorProto.Descriptor; } + } + + public override EnumDescriptorProto DefaultInstanceForType { + get { return EnumDescriptorProto.DefaultInstance; } + } + + public override EnumDescriptorProto BuildPartial() { + result.value_.MakeReadOnly(); + EnumDescriptorProto returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is EnumDescriptorProto) { + return MergeFrom((EnumDescriptorProto) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(EnumDescriptorProto other) { + if (other == EnumDescriptorProto.DefaultInstance) return this; + if (other.HasName) { + Name = other.Name; + } + if (other.value_.Count != 0) { + base.AddRange(other.value_, result.value_); + } + if (other.HasOptions) { + MergeOptions(other.Options); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddValue(subBuilder.BuildPartial()); + break; + } + case 26: { + global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.CreateBuilder(); + if (HasOptions) { + subBuilder.MergeFrom(Options); + } + input.ReadMessage(subBuilder, extensionRegistry); + Options = subBuilder.BuildPartial(); + break; + } + } + } + } + + + public bool HasName { + get { return result.HasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + result.hasName = false; + result.name_ = ""; + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> ValueList { + get { return result.value_; } + } + public int ValueCount { + get { return result.ValueCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto GetValue(int index) { + return result.GetValue(index); + } + public Builder SetValue(int index, global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto value) { + result.value_[index] = value; + return this; + } + public Builder SetValue(int index, global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.Builder builderForValue) { + result.value_[index] = builderForValue.Build(); + return this; + } + public Builder AddValue(global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto value) { + result.value_.Add(value); + return this; + } + public Builder AddValue(global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.Builder builderForValue) { + result.value_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeValue(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> values) { + base.AddRange(values, result.value_); + return this; + } + public Builder ClearValue() { + result.value_.Clear(); + return this; + } + + public bool HasOptions { + get { return result.HasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions Options { + get { return result.Options; } + set { SetOptions(value); } + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions value) { + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.Build(); + return this; + } + public Builder MergeOptions(global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions value) { + if (result.HasOptions && + result.options_ != global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.DefaultInstance) { + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.CreateBuilder(result.options_).MergeFrom(value).BuildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder ClearOptions() { + result.hasOptions = false; + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.DefaultInstance; + return this; + } + } + } + + public sealed partial class EnumValueDescriptorProto : pb::GeneratedMessage<EnumValueDescriptorProto, EnumValueDescriptorProto.Builder> { + private static readonly EnumValueDescriptorProto defaultInstance = new Builder().BuildPartial(); + public static EnumValueDescriptorProto DefaultInstance { + get { return defaultInstance; } + } + + public override EnumValueDescriptorProto DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override EnumValueDescriptorProto ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueDescriptorProto__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<EnumValueDescriptorProto, EnumValueDescriptorProto.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable; } + } + + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + private bool hasNumber; + private int number_ = 0; + public bool HasNumber { + get { return hasNumber; } + } + public int Number { + get { return number_; } + } + + private bool hasOptions; + private global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions options_ = global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.DefaultInstance; + public bool HasOptions { + get { return hasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions Options { + get { return options_; } + } + + public override bool IsInitialized { + get { + if (HasOptions) { + if (!Options.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasName) { + output.WriteString(1, Name); + } + if (HasNumber) { + output.WriteInt32(2, Number); + } + if (HasOptions) { + output.WriteMessage(3, Options); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + if (HasNumber) { + size += pb::CodedOutputStream.ComputeInt32Size(2, Number); + } + if (HasOptions) { + size += pb::CodedOutputStream.ComputeMessageSize(3, Options); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static EnumValueDescriptorProto ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumValueDescriptorProto ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumValueDescriptorProto ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumValueDescriptorProto ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumValueDescriptorProto ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumValueDescriptorProto ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static EnumValueDescriptorProto ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumValueDescriptorProto ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(EnumValueDescriptorProto prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<EnumValueDescriptorProto, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + EnumValueDescriptorProto result = new EnumValueDescriptorProto(); + + protected override EnumValueDescriptorProto MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new EnumValueDescriptorProto(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return EnumValueDescriptorProto.Descriptor; } + } + + public override EnumValueDescriptorProto DefaultInstanceForType { + get { return EnumValueDescriptorProto.DefaultInstance; } + } + + public override EnumValueDescriptorProto BuildPartial() { + EnumValueDescriptorProto returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is EnumValueDescriptorProto) { + return MergeFrom((EnumValueDescriptorProto) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(EnumValueDescriptorProto other) { + if (other == EnumValueDescriptorProto.DefaultInstance) return this; + if (other.HasName) { + Name = other.Name; + } + if (other.HasNumber) { + Number = other.Number; + } + if (other.HasOptions) { + MergeOptions(other.Options); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + Name = input.ReadString(); + break; + } + case 16: { + Number = input.ReadInt32(); + break; + } + case 26: { + global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.CreateBuilder(); + if (HasOptions) { + subBuilder.MergeFrom(Options); + } + input.ReadMessage(subBuilder, extensionRegistry); + Options = subBuilder.BuildPartial(); + break; + } + } + } + } + + + public bool HasName { + get { return result.HasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + result.hasName = false; + result.name_ = ""; + return this; + } + + public bool HasNumber { + get { return result.HasNumber; } + } + public int Number { + get { return result.Number; } + set { SetNumber(value); } + } + public Builder SetNumber(int value) { + result.hasNumber = true; + result.number_ = value; + return this; + } + public Builder ClearNumber() { + result.hasNumber = false; + result.number_ = 0; + return this; + } + + public bool HasOptions { + get { return result.HasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions Options { + get { return result.Options; } + set { SetOptions(value); } + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions value) { + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.Build(); + return this; + } + public Builder MergeOptions(global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions value) { + if (result.HasOptions && + result.options_ != global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.DefaultInstance) { + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.CreateBuilder(result.options_).MergeFrom(value).BuildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder ClearOptions() { + result.hasOptions = false; + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.DefaultInstance; + return this; + } + } + } + + public sealed partial class ServiceDescriptorProto : pb::GeneratedMessage<ServiceDescriptorProto, ServiceDescriptorProto.Builder> { + private static readonly ServiceDescriptorProto defaultInstance = new Builder().BuildPartial(); + public static ServiceDescriptorProto DefaultInstance { + get { return defaultInstance; } + } + + public override ServiceDescriptorProto DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override ServiceDescriptorProto ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceDescriptorProto__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<ServiceDescriptorProto, ServiceDescriptorProto.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable; } + } + + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> method_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> MethodList { + get { return method_; } + } + public int MethodCount { + get { return method_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto GetMethod(int index) { + return method_[index]; + } + + private bool hasOptions; + private global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions options_ = global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.DefaultInstance; + public bool HasOptions { + get { return hasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions Options { + get { return options_; } + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto element in MethodList) { + if (!element.IsInitialized) return false; + } + if (HasOptions) { + if (!Options.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasName) { + output.WriteString(1, Name); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto element in MethodList) { + output.WriteMessage(2, element); + } + if (HasOptions) { + output.WriteMessage(3, Options); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto element in MethodList) { + size += pb::CodedOutputStream.ComputeMessageSize(2, element); + } + if (HasOptions) { + size += pb::CodedOutputStream.ComputeMessageSize(3, Options); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static ServiceDescriptorProto ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ServiceDescriptorProto ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ServiceDescriptorProto ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ServiceDescriptorProto ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ServiceDescriptorProto ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ServiceDescriptorProto ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static ServiceDescriptorProto ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ServiceDescriptorProto ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(ServiceDescriptorProto prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<ServiceDescriptorProto, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + ServiceDescriptorProto result = new ServiceDescriptorProto(); + + protected override ServiceDescriptorProto MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new ServiceDescriptorProto(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return ServiceDescriptorProto.Descriptor; } + } + + public override ServiceDescriptorProto DefaultInstanceForType { + get { return ServiceDescriptorProto.DefaultInstance; } + } + + public override ServiceDescriptorProto BuildPartial() { + result.method_.MakeReadOnly(); + ServiceDescriptorProto returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is ServiceDescriptorProto) { + return MergeFrom((ServiceDescriptorProto) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(ServiceDescriptorProto other) { + if (other == ServiceDescriptorProto.DefaultInstance) return this; + if (other.HasName) { + Name = other.Name; + } + if (other.method_.Count != 0) { + base.AddRange(other.method_, result.method_); + } + if (other.HasOptions) { + MergeOptions(other.Options); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddMethod(subBuilder.BuildPartial()); + break; + } + case 26: { + global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.CreateBuilder(); + if (HasOptions) { + subBuilder.MergeFrom(Options); + } + input.ReadMessage(subBuilder, extensionRegistry); + Options = subBuilder.BuildPartial(); + break; + } + } + } + } + + + public bool HasName { + get { return result.HasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + result.hasName = false; + result.name_ = ""; + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> MethodList { + get { return result.method_; } + } + public int MethodCount { + get { return result.MethodCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto GetMethod(int index) { + return result.GetMethod(index); + } + public Builder SetMethod(int index, global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto value) { + result.method_[index] = value; + return this; + } + public Builder SetMethod(int index, global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.Builder builderForValue) { + result.method_[index] = builderForValue.Build(); + return this; + } + public Builder AddMethod(global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto value) { + result.method_.Add(value); + return this; + } + public Builder AddMethod(global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.Builder builderForValue) { + result.method_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeMethod(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> values) { + base.AddRange(values, result.method_); + return this; + } + public Builder ClearMethod() { + result.method_.Clear(); + return this; + } + + public bool HasOptions { + get { return result.HasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions Options { + get { return result.Options; } + set { SetOptions(value); } + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions value) { + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.Build(); + return this; + } + public Builder MergeOptions(global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions value) { + if (result.HasOptions && + result.options_ != global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.DefaultInstance) { + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.CreateBuilder(result.options_).MergeFrom(value).BuildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder ClearOptions() { + result.hasOptions = false; + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.DefaultInstance; + return this; + } + } + } + + public sealed partial class MethodDescriptorProto : pb::GeneratedMessage<MethodDescriptorProto, MethodDescriptorProto.Builder> { + private static readonly MethodDescriptorProto defaultInstance = new Builder().BuildPartial(); + public static MethodDescriptorProto DefaultInstance { + get { return defaultInstance; } + } + + public override MethodDescriptorProto DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override MethodDescriptorProto ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodDescriptorProto__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<MethodDescriptorProto, MethodDescriptorProto.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable; } + } + + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + private bool hasInputType; + private string inputType_ = ""; + public bool HasInputType { + get { return hasInputType; } + } + public string InputType { + get { return inputType_; } + } + + private bool hasOutputType; + private string outputType_ = ""; + public bool HasOutputType { + get { return hasOutputType; } + } + public string OutputType { + get { return outputType_; } + } + + private bool hasOptions; + private global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions options_ = global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.DefaultInstance; + public bool HasOptions { + get { return hasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions Options { + get { return options_; } + } + + public override bool IsInitialized { + get { + if (HasOptions) { + if (!Options.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasName) { + output.WriteString(1, Name); + } + if (HasInputType) { + output.WriteString(2, InputType); + } + if (HasOutputType) { + output.WriteString(3, OutputType); + } + if (HasOptions) { + output.WriteMessage(4, Options); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + if (HasInputType) { + size += pb::CodedOutputStream.ComputeStringSize(2, InputType); + } + if (HasOutputType) { + size += pb::CodedOutputStream.ComputeStringSize(3, OutputType); + } + if (HasOptions) { + size += pb::CodedOutputStream.ComputeMessageSize(4, Options); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static MethodDescriptorProto ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static MethodDescriptorProto ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static MethodDescriptorProto ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static MethodDescriptorProto ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static MethodDescriptorProto ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static MethodDescriptorProto ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static MethodDescriptorProto ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static MethodDescriptorProto ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(MethodDescriptorProto prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<MethodDescriptorProto, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + MethodDescriptorProto result = new MethodDescriptorProto(); + + protected override MethodDescriptorProto MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new MethodDescriptorProto(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return MethodDescriptorProto.Descriptor; } + } + + public override MethodDescriptorProto DefaultInstanceForType { + get { return MethodDescriptorProto.DefaultInstance; } + } + + public override MethodDescriptorProto BuildPartial() { + MethodDescriptorProto returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is MethodDescriptorProto) { + return MergeFrom((MethodDescriptorProto) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(MethodDescriptorProto other) { + if (other == MethodDescriptorProto.DefaultInstance) return this; + if (other.HasName) { + Name = other.Name; + } + if (other.HasInputType) { + InputType = other.InputType; + } + if (other.HasOutputType) { + OutputType = other.OutputType; + } + if (other.HasOptions) { + MergeOptions(other.Options); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + InputType = input.ReadString(); + break; + } + case 26: { + OutputType = input.ReadString(); + break; + } + case 34: { + global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.CreateBuilder(); + if (HasOptions) { + subBuilder.MergeFrom(Options); + } + input.ReadMessage(subBuilder, extensionRegistry); + Options = subBuilder.BuildPartial(); + break; + } + } + } + } + + + public bool HasName { + get { return result.HasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + result.hasName = false; + result.name_ = ""; + return this; + } + + public bool HasInputType { + get { return result.HasInputType; } + } + public string InputType { + get { return result.InputType; } + set { SetInputType(value); } + } + public Builder SetInputType(string value) { + result.hasInputType = true; + result.inputType_ = value; + return this; + } + public Builder ClearInputType() { + result.hasInputType = false; + result.inputType_ = ""; + return this; + } + + public bool HasOutputType { + get { return result.HasOutputType; } + } + public string OutputType { + get { return result.OutputType; } + set { SetOutputType(value); } + } + public Builder SetOutputType(string value) { + result.hasOutputType = true; + result.outputType_ = value; + return this; + } + public Builder ClearOutputType() { + result.hasOutputType = false; + result.outputType_ = ""; + return this; + } + + public bool HasOptions { + get { return result.HasOptions; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions Options { + get { return result.Options; } + set { SetOptions(value); } + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions value) { + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder SetOptions(global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.Build(); + return this; + } + public Builder MergeOptions(global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions value) { + if (result.HasOptions && + result.options_ != global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.DefaultInstance) { + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.CreateBuilder(result.options_).MergeFrom(value).BuildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder ClearOptions() { + result.hasOptions = false; + result.options_ = global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.DefaultInstance; + return this; + } + } + } + + public sealed partial class FileOptions : pb::ExtendableMessage<FileOptions, FileOptions.Builder> { + private static readonly FileOptions defaultInstance = new Builder().BuildPartial(); + public static FileOptions DefaultInstance { + get { return defaultInstance; } + } + + public override FileOptions DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override FileOptions ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileOptions__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<FileOptions, FileOptions.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileOptions__FieldAccessorTable; } + } + + #region Nested types + public static class Types { + public enum OptimizeMode { + SPEED = 1, + CODE_SIZE = 2, + } + + } + #endregion + + private bool hasJavaPackage; + private string javaPackage_ = ""; + public bool HasJavaPackage { + get { return hasJavaPackage; } + } + public string JavaPackage { + get { return javaPackage_; } + } + + private bool hasJavaOuterClassname; + private string javaOuterClassname_ = ""; + public bool HasJavaOuterClassname { + get { return hasJavaOuterClassname; } + } + public string JavaOuterClassname { + get { return javaOuterClassname_; } + } + + private bool hasJavaMultipleFiles; + private bool javaMultipleFiles_ = false; + public bool HasJavaMultipleFiles { + get { return hasJavaMultipleFiles; } + } + public bool JavaMultipleFiles { + get { return javaMultipleFiles_; } + } + + private bool hasOptimizeFor; + private global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode optimizeFor_ = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.CODE_SIZE; + public bool HasOptimizeFor { + get { return hasOptimizeFor; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode OptimizeFor { + get { return optimizeFor_; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return uninterpretedOption_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return uninterpretedOption_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + if (!element.IsInitialized) return false; + } + if (!ExtensionsAreInitialized) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + pb::ExtendableMessage<FileOptions, FileOptions.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + if (HasJavaPackage) { + output.WriteString(1, JavaPackage); + } + if (HasJavaOuterClassname) { + output.WriteString(8, JavaOuterClassname); + } + if (HasOptimizeFor) { + output.WriteEnum(9, (int) OptimizeFor); + } + if (HasJavaMultipleFiles) { + output.WriteBool(10, JavaMultipleFiles); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + output.WriteMessage(999, element); + } + extensionWriter.WriteUntil(536870912, output); + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasJavaPackage) { + size += pb::CodedOutputStream.ComputeStringSize(1, JavaPackage); + } + if (HasJavaOuterClassname) { + size += pb::CodedOutputStream.ComputeStringSize(8, JavaOuterClassname); + } + if (HasJavaMultipleFiles) { + size += pb::CodedOutputStream.ComputeBoolSize(10, JavaMultipleFiles); + } + if (HasOptimizeFor) { + size += pb::CodedOutputStream.ComputeEnumSize(9, (int) OptimizeFor); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + size += pb::CodedOutputStream.ComputeMessageSize(999, element); + } + size += ExtensionsSerializedSize; + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static FileOptions ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FileOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FileOptions ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FileOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FileOptions ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FileOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static FileOptions ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FileOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(FileOptions prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::ExtendableBuilder<FileOptions, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + FileOptions result = new FileOptions(); + + protected override FileOptions MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new FileOptions(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return FileOptions.Descriptor; } + } + + public override FileOptions DefaultInstanceForType { + get { return FileOptions.DefaultInstance; } + } + + public override FileOptions BuildPartial() { + result.uninterpretedOption_.MakeReadOnly(); + FileOptions returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is FileOptions) { + return MergeFrom((FileOptions) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(FileOptions other) { + if (other == FileOptions.DefaultInstance) return this; + if (other.HasJavaPackage) { + JavaPackage = other.JavaPackage; + } + if (other.HasJavaOuterClassname) { + JavaOuterClassname = other.JavaOuterClassname; + } + if (other.HasJavaMultipleFiles) { + JavaMultipleFiles = other.JavaMultipleFiles; + } + if (other.HasOptimizeFor) { + OptimizeFor = other.OptimizeFor; + } + if (other.uninterpretedOption_.Count != 0) { + base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + JavaPackage = input.ReadString(); + break; + } + case 66: { + JavaOuterClassname = input.ReadString(); + break; + } + case 72: { + int rawValue = input.ReadEnum(); + if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode), rawValue)) { + unknownFields.MergeVarintField(9, (ulong) rawValue); + } else { + OptimizeFor = (global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode) rawValue; + } + break; + } + case 80: { + JavaMultipleFiles = input.ReadBool(); + break; + } + case 7994: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddUninterpretedOption(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public bool HasJavaPackage { + get { return result.HasJavaPackage; } + } + public string JavaPackage { + get { return result.JavaPackage; } + set { SetJavaPackage(value); } + } + public Builder SetJavaPackage(string value) { + result.hasJavaPackage = true; + result.javaPackage_ = value; + return this; + } + public Builder ClearJavaPackage() { + result.hasJavaPackage = false; + result.javaPackage_ = ""; + return this; + } + + public bool HasJavaOuterClassname { + get { return result.HasJavaOuterClassname; } + } + public string JavaOuterClassname { + get { return result.JavaOuterClassname; } + set { SetJavaOuterClassname(value); } + } + public Builder SetJavaOuterClassname(string value) { + result.hasJavaOuterClassname = true; + result.javaOuterClassname_ = value; + return this; + } + public Builder ClearJavaOuterClassname() { + result.hasJavaOuterClassname = false; + result.javaOuterClassname_ = ""; + return this; + } + + public bool HasJavaMultipleFiles { + get { return result.HasJavaMultipleFiles; } + } + public bool JavaMultipleFiles { + get { return result.JavaMultipleFiles; } + set { SetJavaMultipleFiles(value); } + } + public Builder SetJavaMultipleFiles(bool value) { + result.hasJavaMultipleFiles = true; + result.javaMultipleFiles_ = value; + return this; + } + public Builder ClearJavaMultipleFiles() { + result.hasJavaMultipleFiles = false; + result.javaMultipleFiles_ = false; + return this; + } + + public bool HasOptimizeFor { + get { return result.HasOptimizeFor; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode OptimizeFor { + get { return result.OptimizeFor; } + set { SetOptimizeFor(value); } + } + public Builder SetOptimizeFor(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode value) { + result.hasOptimizeFor = true; + result.optimizeFor_ = value; + return this; + } + public Builder ClearOptimizeFor() { + result.hasOptimizeFor = false; + result.optimizeFor_ = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.CODE_SIZE; + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return result.uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return result.UninterpretedOptionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return result.GetUninterpretedOption(index); + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_[index] = value; + return this; + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_[index] = builderForValue.Build(); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_.Add(value); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeUninterpretedOption(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> values) { + base.AddRange(values, result.uninterpretedOption_); + return this; + } + public Builder ClearUninterpretedOption() { + result.uninterpretedOption_.Clear(); + return this; + } + } + } + + public sealed partial class MessageOptions : pb::ExtendableMessage<MessageOptions, MessageOptions.Builder> { + private static readonly MessageOptions defaultInstance = new Builder().BuildPartial(); + public static MessageOptions DefaultInstance { + get { return defaultInstance; } + } + + public override MessageOptions DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override MessageOptions ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MessageOptions__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<MessageOptions, MessageOptions.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MessageOptions__FieldAccessorTable; } + } + + private bool hasMessageSetWireFormat; + private bool messageSetWireFormat_ = false; + public bool HasMessageSetWireFormat { + get { return hasMessageSetWireFormat; } + } + public bool MessageSetWireFormat { + get { return messageSetWireFormat_; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return uninterpretedOption_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return uninterpretedOption_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + if (!element.IsInitialized) return false; + } + if (!ExtensionsAreInitialized) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + pb::ExtendableMessage<MessageOptions, MessageOptions.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + if (HasMessageSetWireFormat) { + output.WriteBool(1, MessageSetWireFormat); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + output.WriteMessage(999, element); + } + extensionWriter.WriteUntil(536870912, output); + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasMessageSetWireFormat) { + size += pb::CodedOutputStream.ComputeBoolSize(1, MessageSetWireFormat); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + size += pb::CodedOutputStream.ComputeMessageSize(999, element); + } + size += ExtensionsSerializedSize; + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static MessageOptions ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static MessageOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static MessageOptions ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static MessageOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static MessageOptions ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static MessageOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static MessageOptions ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static MessageOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(MessageOptions prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::ExtendableBuilder<MessageOptions, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + MessageOptions result = new MessageOptions(); + + protected override MessageOptions MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new MessageOptions(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return MessageOptions.Descriptor; } + } + + public override MessageOptions DefaultInstanceForType { + get { return MessageOptions.DefaultInstance; } + } + + public override MessageOptions BuildPartial() { + result.uninterpretedOption_.MakeReadOnly(); + MessageOptions returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is MessageOptions) { + return MergeFrom((MessageOptions) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(MessageOptions other) { + if (other == MessageOptions.DefaultInstance) return this; + if (other.HasMessageSetWireFormat) { + MessageSetWireFormat = other.MessageSetWireFormat; + } + if (other.uninterpretedOption_.Count != 0) { + base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 8: { + MessageSetWireFormat = input.ReadBool(); + break; + } + case 7994: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddUninterpretedOption(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public bool HasMessageSetWireFormat { + get { return result.HasMessageSetWireFormat; } + } + public bool MessageSetWireFormat { + get { return result.MessageSetWireFormat; } + set { SetMessageSetWireFormat(value); } + } + public Builder SetMessageSetWireFormat(bool value) { + result.hasMessageSetWireFormat = true; + result.messageSetWireFormat_ = value; + return this; + } + public Builder ClearMessageSetWireFormat() { + result.hasMessageSetWireFormat = false; + result.messageSetWireFormat_ = false; + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return result.uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return result.UninterpretedOptionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return result.GetUninterpretedOption(index); + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_[index] = value; + return this; + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_[index] = builderForValue.Build(); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_.Add(value); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeUninterpretedOption(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> values) { + base.AddRange(values, result.uninterpretedOption_); + return this; + } + public Builder ClearUninterpretedOption() { + result.uninterpretedOption_.Clear(); + return this; + } + } + } + + public sealed partial class FieldOptions : pb::ExtendableMessage<FieldOptions, FieldOptions.Builder> { + private static readonly FieldOptions defaultInstance = new Builder().BuildPartial(); + public static FieldOptions DefaultInstance { + get { return defaultInstance; } + } + + public override FieldOptions DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override FieldOptions ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldOptions__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<FieldOptions, FieldOptions.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldOptions__FieldAccessorTable; } + } + + #region Nested types + public static class Types { + public enum CType { + CORD = 1, + STRING_PIECE = 2, + } + + } + #endregion + + private bool hasCtype; + private global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType ctype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType.CORD; + public bool HasCtype { + get { return hasCtype; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType Ctype { + get { return ctype_; } + } + + private bool hasExperimentalMapKey; + private string experimentalMapKey_ = ""; + public bool HasExperimentalMapKey { + get { return hasExperimentalMapKey; } + } + public string ExperimentalMapKey { + get { return experimentalMapKey_; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return uninterpretedOption_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return uninterpretedOption_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + if (!element.IsInitialized) return false; + } + if (!ExtensionsAreInitialized) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + pb::ExtendableMessage<FieldOptions, FieldOptions.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + if (HasCtype) { + output.WriteEnum(1, (int) Ctype); + } + if (HasExperimentalMapKey) { + output.WriteString(9, ExperimentalMapKey); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + output.WriteMessage(999, element); + } + extensionWriter.WriteUntil(536870912, output); + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasCtype) { + size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Ctype); + } + if (HasExperimentalMapKey) { + size += pb::CodedOutputStream.ComputeStringSize(9, ExperimentalMapKey); + } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + size += pb::CodedOutputStream.ComputeMessageSize(999, element); + } + size += ExtensionsSerializedSize; + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static FieldOptions ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FieldOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FieldOptions ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static FieldOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static FieldOptions ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FieldOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static FieldOptions ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static FieldOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(FieldOptions prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::ExtendableBuilder<FieldOptions, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + FieldOptions result = new FieldOptions(); + + protected override FieldOptions MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new FieldOptions(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return FieldOptions.Descriptor; } + } + + public override FieldOptions DefaultInstanceForType { + get { return FieldOptions.DefaultInstance; } + } + + public override FieldOptions BuildPartial() { + result.uninterpretedOption_.MakeReadOnly(); + FieldOptions returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is FieldOptions) { + return MergeFrom((FieldOptions) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(FieldOptions other) { + if (other == FieldOptions.DefaultInstance) return this; + if (other.HasCtype) { + Ctype = other.Ctype; + } + if (other.HasExperimentalMapKey) { + ExperimentalMapKey = other.ExperimentalMapKey; + } + if (other.uninterpretedOption_.Count != 0) { + base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 8: { + int rawValue = input.ReadEnum(); + if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType), rawValue)) { + unknownFields.MergeVarintField(1, (ulong) rawValue); + } else { + Ctype = (global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType) rawValue; + } + break; + } + case 74: { + ExperimentalMapKey = input.ReadString(); + break; + } + case 7994: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddUninterpretedOption(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public bool HasCtype { + get { return result.HasCtype; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType Ctype { + get { return result.Ctype; } + set { SetCtype(value); } + } + public Builder SetCtype(global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType value) { + result.hasCtype = true; + result.ctype_ = value; + return this; + } + public Builder ClearCtype() { + result.hasCtype = false; + result.ctype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType.CORD; + return this; + } + + public bool HasExperimentalMapKey { + get { return result.HasExperimentalMapKey; } + } + public string ExperimentalMapKey { + get { return result.ExperimentalMapKey; } + set { SetExperimentalMapKey(value); } + } + public Builder SetExperimentalMapKey(string value) { + result.hasExperimentalMapKey = true; + result.experimentalMapKey_ = value; + return this; + } + public Builder ClearExperimentalMapKey() { + result.hasExperimentalMapKey = false; + result.experimentalMapKey_ = ""; + return this; + } + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return result.uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return result.UninterpretedOptionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return result.GetUninterpretedOption(index); + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_[index] = value; + return this; + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_[index] = builderForValue.Build(); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_.Add(value); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeUninterpretedOption(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> values) { + base.AddRange(values, result.uninterpretedOption_); + return this; + } + public Builder ClearUninterpretedOption() { + result.uninterpretedOption_.Clear(); + return this; + } + } + } + + public sealed partial class EnumOptions : pb::ExtendableMessage<EnumOptions, EnumOptions.Builder> { + private static readonly EnumOptions defaultInstance = new Builder().BuildPartial(); + public static EnumOptions DefaultInstance { + get { return defaultInstance; } + } + + public override EnumOptions DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override EnumOptions ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumOptions__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<EnumOptions, EnumOptions.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumOptions__FieldAccessorTable; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return uninterpretedOption_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return uninterpretedOption_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + if (!element.IsInitialized) return false; + } + if (!ExtensionsAreInitialized) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + pb::ExtendableMessage<EnumOptions, EnumOptions.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + output.WriteMessage(999, element); + } + extensionWriter.WriteUntil(536870912, output); + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + size += pb::CodedOutputStream.ComputeMessageSize(999, element); + } + size += ExtensionsSerializedSize; + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static EnumOptions ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumOptions ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumOptions ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static EnumOptions ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(EnumOptions prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::ExtendableBuilder<EnumOptions, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + EnumOptions result = new EnumOptions(); + + protected override EnumOptions MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new EnumOptions(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return EnumOptions.Descriptor; } + } + + public override EnumOptions DefaultInstanceForType { + get { return EnumOptions.DefaultInstance; } + } + + public override EnumOptions BuildPartial() { + result.uninterpretedOption_.MakeReadOnly(); + EnumOptions returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is EnumOptions) { + return MergeFrom((EnumOptions) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(EnumOptions other) { + if (other == EnumOptions.DefaultInstance) return this; + if (other.uninterpretedOption_.Count != 0) { + base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 7994: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddUninterpretedOption(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return result.uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return result.UninterpretedOptionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return result.GetUninterpretedOption(index); + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_[index] = value; + return this; + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_[index] = builderForValue.Build(); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_.Add(value); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeUninterpretedOption(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> values) { + base.AddRange(values, result.uninterpretedOption_); + return this; + } + public Builder ClearUninterpretedOption() { + result.uninterpretedOption_.Clear(); + return this; + } + } + } + + public sealed partial class EnumValueOptions : pb::ExtendableMessage<EnumValueOptions, EnumValueOptions.Builder> { + private static readonly EnumValueOptions defaultInstance = new Builder().BuildPartial(); + public static EnumValueOptions DefaultInstance { + get { return defaultInstance; } + } + + public override EnumValueOptions DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override EnumValueOptions ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueOptions__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<EnumValueOptions, EnumValueOptions.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return uninterpretedOption_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return uninterpretedOption_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + if (!element.IsInitialized) return false; + } + if (!ExtensionsAreInitialized) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + pb::ExtendableMessage<EnumValueOptions, EnumValueOptions.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + output.WriteMessage(999, element); + } + extensionWriter.WriteUntil(536870912, output); + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + size += pb::CodedOutputStream.ComputeMessageSize(999, element); + } + size += ExtensionsSerializedSize; + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static EnumValueOptions ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumValueOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumValueOptions ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static EnumValueOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static EnumValueOptions ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumValueOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static EnumValueOptions ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static EnumValueOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(EnumValueOptions prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::ExtendableBuilder<EnumValueOptions, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + EnumValueOptions result = new EnumValueOptions(); + + protected override EnumValueOptions MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new EnumValueOptions(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return EnumValueOptions.Descriptor; } + } + + public override EnumValueOptions DefaultInstanceForType { + get { return EnumValueOptions.DefaultInstance; } + } + + public override EnumValueOptions BuildPartial() { + result.uninterpretedOption_.MakeReadOnly(); + EnumValueOptions returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is EnumValueOptions) { + return MergeFrom((EnumValueOptions) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(EnumValueOptions other) { + if (other == EnumValueOptions.DefaultInstance) return this; + if (other.uninterpretedOption_.Count != 0) { + base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 7994: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddUninterpretedOption(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return result.uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return result.UninterpretedOptionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return result.GetUninterpretedOption(index); + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_[index] = value; + return this; + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_[index] = builderForValue.Build(); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_.Add(value); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeUninterpretedOption(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> values) { + base.AddRange(values, result.uninterpretedOption_); + return this; + } + public Builder ClearUninterpretedOption() { + result.uninterpretedOption_.Clear(); + return this; + } + } + } + + public sealed partial class ServiceOptions : pb::ExtendableMessage<ServiceOptions, ServiceOptions.Builder> { + private static readonly ServiceOptions defaultInstance = new Builder().BuildPartial(); + public static ServiceOptions DefaultInstance { + get { return defaultInstance; } + } + + public override ServiceOptions DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override ServiceOptions ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceOptions__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<ServiceOptions, ServiceOptions.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceOptions__FieldAccessorTable; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return uninterpretedOption_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return uninterpretedOption_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + if (!element.IsInitialized) return false; + } + if (!ExtensionsAreInitialized) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + pb::ExtendableMessage<ServiceOptions, ServiceOptions.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + output.WriteMessage(999, element); + } + extensionWriter.WriteUntil(536870912, output); + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + size += pb::CodedOutputStream.ComputeMessageSize(999, element); + } + size += ExtensionsSerializedSize; + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static ServiceOptions ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ServiceOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ServiceOptions ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ServiceOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ServiceOptions ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ServiceOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static ServiceOptions ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ServiceOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(ServiceOptions prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::ExtendableBuilder<ServiceOptions, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + ServiceOptions result = new ServiceOptions(); + + protected override ServiceOptions MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new ServiceOptions(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return ServiceOptions.Descriptor; } + } + + public override ServiceOptions DefaultInstanceForType { + get { return ServiceOptions.DefaultInstance; } + } + + public override ServiceOptions BuildPartial() { + result.uninterpretedOption_.MakeReadOnly(); + ServiceOptions returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is ServiceOptions) { + return MergeFrom((ServiceOptions) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(ServiceOptions other) { + if (other == ServiceOptions.DefaultInstance) return this; + if (other.uninterpretedOption_.Count != 0) { + base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 7994: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddUninterpretedOption(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return result.uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return result.UninterpretedOptionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return result.GetUninterpretedOption(index); + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_[index] = value; + return this; + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_[index] = builderForValue.Build(); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_.Add(value); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeUninterpretedOption(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> values) { + base.AddRange(values, result.uninterpretedOption_); + return this; + } + public Builder ClearUninterpretedOption() { + result.uninterpretedOption_.Clear(); + return this; + } + } + } + + public sealed partial class MethodOptions : pb::ExtendableMessage<MethodOptions, MethodOptions.Builder> { + private static readonly MethodOptions defaultInstance = new Builder().BuildPartial(); + public static MethodOptions DefaultInstance { + get { return defaultInstance; } + } + + public override MethodOptions DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override MethodOptions ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodOptions__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<MethodOptions, MethodOptions.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodOptions__FieldAccessorTable; } + } + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return uninterpretedOption_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return uninterpretedOption_[index]; + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + if (!element.IsInitialized) return false; + } + if (!ExtensionsAreInitialized) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + pb::ExtendableMessage<MethodOptions, MethodOptions.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + output.WriteMessage(999, element); + } + extensionWriter.WriteUntil(536870912, output); + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) { + size += pb::CodedOutputStream.ComputeMessageSize(999, element); + } + size += ExtensionsSerializedSize; + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static MethodOptions ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static MethodOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static MethodOptions ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static MethodOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static MethodOptions ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static MethodOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static MethodOptions ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static MethodOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(MethodOptions prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::ExtendableBuilder<MethodOptions, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + MethodOptions result = new MethodOptions(); + + protected override MethodOptions MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new MethodOptions(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return MethodOptions.Descriptor; } + } + + public override MethodOptions DefaultInstanceForType { + get { return MethodOptions.DefaultInstance; } + } + + public override MethodOptions BuildPartial() { + result.uninterpretedOption_.MakeReadOnly(); + MethodOptions returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is MethodOptions) { + return MergeFrom((MethodOptions) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(MethodOptions other) { + if (other == MethodOptions.DefaultInstance) return this; + if (other.uninterpretedOption_.Count != 0) { + base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 7994: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddUninterpretedOption(subBuilder.BuildPartial()); + break; + } + } + } + } + + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList { + get { return result.uninterpretedOption_; } + } + public int UninterpretedOptionCount { + get { return result.UninterpretedOptionCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption GetUninterpretedOption(int index) { + return result.GetUninterpretedOption(index); + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_[index] = value; + return this; + } + public Builder SetUninterpretedOption(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_[index] = builderForValue.Build(); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption value) { + result.uninterpretedOption_.Add(value); + return this; + } + public Builder AddUninterpretedOption(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + result.uninterpretedOption_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeUninterpretedOption(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> values) { + base.AddRange(values, result.uninterpretedOption_); + return this; + } + public Builder ClearUninterpretedOption() { + result.uninterpretedOption_.Clear(); + return this; + } + } + } + + public sealed partial class UninterpretedOption : pb::GeneratedMessage<UninterpretedOption, UninterpretedOption.Builder> { + private static readonly UninterpretedOption defaultInstance = new Builder().BuildPartial(); + public static UninterpretedOption DefaultInstance { + get { return defaultInstance; } + } + + public override UninterpretedOption DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override UninterpretedOption ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<UninterpretedOption, UninterpretedOption.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable; } + } + + #region Nested types + public static class Types { + public sealed partial class NamePart : pb::GeneratedMessage<NamePart, NamePart.Builder> { + private static readonly NamePart defaultInstance = new Builder().BuildPartial(); + public static NamePart DefaultInstance { + get { return defaultInstance; } + } + + public override NamePart DefaultInstanceForType { + get { return defaultInstance; } + } + + protected override NamePart ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption_NamePart__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable<NamePart, NamePart.Builder> InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable; } + } + + private bool hasNamePart; + private string namePart_ = ""; + public bool HasNamePart { + get { return hasNamePart; } + } + public string NamePart_ { + get { return namePart_; } + } + + private bool hasIsExtension; + private bool isExtension_ = false; + public bool HasIsExtension { + get { return hasIsExtension; } + } + public bool IsExtension { + get { return isExtension_; } + } + + public override bool IsInitialized { + get { + if (!hasNamePart) return false; + if (!hasIsExtension) return false; + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + if (HasNamePart) { + output.WriteString(1, NamePart_); + } + if (HasIsExtension) { + output.WriteBool(2, IsExtension); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (HasNamePart) { + size += pb::CodedOutputStream.ComputeStringSize(1, NamePart_); + } + if (HasIsExtension) { + size += pb::CodedOutputStream.ComputeBoolSize(2, IsExtension); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static NamePart ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static NamePart ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static NamePart ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static NamePart ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static NamePart ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static NamePart ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static NamePart ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static NamePart ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(NamePart prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<NamePart, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + NamePart result = new NamePart(); + + protected override NamePart MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new NamePart(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return NamePart.Descriptor; } + } + + public override NamePart DefaultInstanceForType { + get { return NamePart.DefaultInstance; } + } + + public override NamePart BuildPartial() { + NamePart returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is NamePart) { + return MergeFrom((NamePart) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(NamePart other) { + if (other == NamePart.DefaultInstance) return this; + if (other.HasNamePart) { + NamePart_ = other.NamePart_; + } + if (other.HasIsExtension) { + IsExtension = other.IsExtension; + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 10: { + NamePart_ = input.ReadString(); + break; + } + case 16: { + IsExtension = input.ReadBool(); + break; + } + } + } + } + + + public bool HasNamePart { + get { return result.HasNamePart; } + } + public string NamePart_ { + get { return result.NamePart_; } + set { SetNamePart(value); } + } + public Builder SetNamePart(string value) { + result.hasNamePart = true; + result.namePart_ = value; + return this; + } + public Builder ClearNamePart() { + result.hasNamePart = false; + result.namePart_ = ""; + return this; + } + + public bool HasIsExtension { + get { return result.HasIsExtension; } + } + public bool IsExtension { + get { return result.IsExtension; } + set { SetIsExtension(value); } + } + public Builder SetIsExtension(bool value) { + result.hasIsExtension = true; + result.isExtension_ = value; + return this; + } + public Builder ClearIsExtension() { + result.hasIsExtension = false; + result.isExtension_ = false; + return this; + } + } + } + + } + #endregion + + private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart> name_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart>(); + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart> NameList { + get { return name_; } + } + public int NameCount { + get { return name_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart GetName(int index) { + return name_[index]; + } + + private bool hasIdentifierValue; + private string identifierValue_ = ""; + public bool HasIdentifierValue { + get { return hasIdentifierValue; } + } + public string IdentifierValue { + get { return identifierValue_; } + } + + private bool hasPositiveIntValue; + private ulong positiveIntValue_ = 0UL; + public bool HasPositiveIntValue { + get { return hasPositiveIntValue; } + } + public ulong PositiveIntValue { + get { return positiveIntValue_; } + } + + private bool hasNegativeIntValue; + private long negativeIntValue_ = 0L; + public bool HasNegativeIntValue { + get { return hasNegativeIntValue; } + } + public long NegativeIntValue { + get { return negativeIntValue_; } + } + + private bool hasDoubleValue; + private double doubleValue_ = 0D; + public bool HasDoubleValue { + get { return hasDoubleValue; } + } + public double DoubleValue { + get { return doubleValue_; } + } + + private bool hasStringValue; + private pb::ByteString stringValue_ = pb::ByteString.Empty; + public bool HasStringValue { + get { return hasStringValue; } + } + public pb::ByteString StringValue { + get { return stringValue_; } + } + + public override bool IsInitialized { + get { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart element in NameList) { + if (!element.IsInitialized) return false; + } + return true; + } + } + + public override void WriteTo(pb::CodedOutputStream output) { + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart element in NameList) { + output.WriteMessage(2, element); + } + if (HasIdentifierValue) { + output.WriteString(3, IdentifierValue); + } + if (HasPositiveIntValue) { + output.WriteUInt64(4, PositiveIntValue); + } + if (HasNegativeIntValue) { + output.WriteInt64(5, NegativeIntValue); + } + if (HasDoubleValue) { + output.WriteDouble(6, DoubleValue); + } + if (HasStringValue) { + output.WriteBytes(7, StringValue); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart element in NameList) { + size += pb::CodedOutputStream.ComputeMessageSize(2, element); + } + if (HasIdentifierValue) { + size += pb::CodedOutputStream.ComputeStringSize(3, IdentifierValue); + } + if (HasPositiveIntValue) { + size += pb::CodedOutputStream.ComputeUInt64Size(4, PositiveIntValue); + } + if (HasNegativeIntValue) { + size += pb::CodedOutputStream.ComputeInt64Size(5, NegativeIntValue); + } + if (HasDoubleValue) { + size += pb::CodedOutputStream.ComputeDoubleSize(6, DoubleValue); + } + if (HasStringValue) { + size += pb::CodedOutputStream.ComputeBytesSize(7, StringValue); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + } + + public static UninterpretedOption ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static UninterpretedOption ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static UninterpretedOption ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static UninterpretedOption ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static UninterpretedOption ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static UninterpretedOption ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static UninterpretedOption ParseFrom(pb::CodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static UninterpretedOption ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Builder CreateBuilder() { return new Builder(); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(UninterpretedOption prototype) { + return (Builder) new Builder().MergeFrom(prototype); + } + + public sealed partial class Builder : pb::GeneratedBuilder<UninterpretedOption, Builder> { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() {} + + UninterpretedOption result = new UninterpretedOption(); + + protected override UninterpretedOption MessageBeingBuilt { + get { return result; } + } + + public override Builder Clear() { + result = new UninterpretedOption(); + return this; + } + + public override Builder Clone() { + return new Builder().MergeFrom(result); + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return UninterpretedOption.Descriptor; } + } + + public override UninterpretedOption DefaultInstanceForType { + get { return UninterpretedOption.DefaultInstance; } + } + + public override UninterpretedOption BuildPartial() { + result.name_.MakeReadOnly(); + UninterpretedOption returnMe = result; + result = null; + return returnMe; + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is UninterpretedOption) { + return MergeFrom((UninterpretedOption) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(UninterpretedOption other) { + if (other == UninterpretedOption.DefaultInstance) return this; + if (other.name_.Count != 0) { + base.AddRange(other.name_, result.name_); + } + if (other.HasIdentifierValue) { + IdentifierValue = other.IdentifierValue; + } + if (other.HasPositiveIntValue) { + PositiveIntValue = other.PositiveIntValue; + } + if (other.HasNegativeIntValue) { + NegativeIntValue = other.NegativeIntValue; + } + if (other.HasDoubleValue) { + DoubleValue = other.DoubleValue; + } + if (other.HasStringValue) { + StringValue = other.StringValue; + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::CodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + while (true) { + uint tag = input.ReadTag(); + switch (tag) { + case 0: { + this.UnknownFields = unknownFields.Build(); + return this; + } + default: { + if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.UnknownFields = unknownFields.Build(); + return this; + } + break; + } + case 18: { + global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.CreateBuilder(); + input.ReadMessage(subBuilder, extensionRegistry); + AddName(subBuilder.BuildPartial()); + break; + } + case 26: { + IdentifierValue = input.ReadString(); + break; + } + case 32: { + PositiveIntValue = input.ReadUInt64(); + break; + } + case 40: { + NegativeIntValue = input.ReadInt64(); + break; + } + case 49: { + DoubleValue = input.ReadDouble(); + break; + } + case 58: { + StringValue = input.ReadBytes(); + break; + } + } + } + } + + + public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart> NameList { + get { return result.name_; } + } + public int NameCount { + get { return result.NameCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart GetName(int index) { + return result.GetName(index); + } + public Builder SetName(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart value) { + result.name_[index] = value; + return this; + } + public Builder SetName(int index, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.Builder builderForValue) { + result.name_[index] = builderForValue.Build(); + return this; + } + public Builder AddName(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart value) { + result.name_.Add(value); + return this; + } + public Builder AddName(global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.Builder builderForValue) { + result.name_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeName(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart> values) { + base.AddRange(values, result.name_); + return this; + } + public Builder ClearName() { + result.name_.Clear(); + return this; + } + + public bool HasIdentifierValue { + get { return result.HasIdentifierValue; } + } + public string IdentifierValue { + get { return result.IdentifierValue; } + set { SetIdentifierValue(value); } + } + public Builder SetIdentifierValue(string value) { + result.hasIdentifierValue = true; + result.identifierValue_ = value; + return this; + } + public Builder ClearIdentifierValue() { + result.hasIdentifierValue = false; + result.identifierValue_ = ""; + return this; + } + + public bool HasPositiveIntValue { + get { return result.HasPositiveIntValue; } + } + public ulong PositiveIntValue { + get { return result.PositiveIntValue; } + set { SetPositiveIntValue(value); } + } + public Builder SetPositiveIntValue(ulong value) { + result.hasPositiveIntValue = true; + result.positiveIntValue_ = value; + return this; + } + public Builder ClearPositiveIntValue() { + result.hasPositiveIntValue = false; + result.positiveIntValue_ = 0UL; + return this; + } + + public bool HasNegativeIntValue { + get { return result.HasNegativeIntValue; } + } + public long NegativeIntValue { + get { return result.NegativeIntValue; } + set { SetNegativeIntValue(value); } + } + public Builder SetNegativeIntValue(long value) { + result.hasNegativeIntValue = true; + result.negativeIntValue_ = value; + return this; + } + public Builder ClearNegativeIntValue() { + result.hasNegativeIntValue = false; + result.negativeIntValue_ = 0L; + return this; + } + + public bool HasDoubleValue { + get { return result.HasDoubleValue; } + } + public double DoubleValue { + get { return result.DoubleValue; } + set { SetDoubleValue(value); } + } + public Builder SetDoubleValue(double value) { + result.hasDoubleValue = true; + result.doubleValue_ = value; + return this; + } + public Builder ClearDoubleValue() { + result.hasDoubleValue = false; + result.doubleValue_ = 0D; + return this; + } + + public bool HasStringValue { + get { return result.HasStringValue; } + } + public pb::ByteString StringValue { + get { return result.StringValue; } + set { SetStringValue(value); } + } + public Builder SetStringValue(pb::ByteString value) { + result.hasStringValue = true; + result.stringValue_ = value; + return this; + } + public Builder ClearStringValue() { + result.hasStringValue = false; + result.stringValue_ = pb::ByteString.Empty; + return this; + } + } + } + + #endregion + +} diff --git a/src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs b/src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs new file mode 100644 index 00000000..1b9f1dc3 --- /dev/null +++ b/src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs @@ -0,0 +1,36 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +namespace Google.ProtocolBuffers.DescriptorProtos { + + /// <summary> + /// Interface implemented by all DescriptorProtos. The generator doesn't + /// emit the interface implementation claim, so PartialClasses.cs contains + /// partial class declarations for each of them. + /// </summary> + /// <typeparam name="TOptions">The associated options protocol buffer type</typeparam> + public interface IDescriptorProto<TOptions> { + + /// <summary> + /// The brief name of the descriptor's target. + /// </summary> + string Name { get; } + + /// <summary> + /// The options for this descriptor. + /// </summary> + TOptions Options { get; } + } +} diff --git a/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs b/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs new file mode 100644 index 00000000..5f414fc2 --- /dev/null +++ b/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file just contains partial classes for each of the +// autogenerated classes, so that they implement +// IDescriptorProto +namespace Google.ProtocolBuffers.DescriptorProtos { + + // TODO(jonskeet): Find a better way of fixing this. It's needed in order to + // cope with unknown fields during initialization. + public partial class DescriptorProtoFile { + private static readonly bool initialized = false; + + internal static bool Bootstrapping { + get { return !initialized; } + } + + static DescriptorProtoFile() { + initialized = true; + } + } + + public partial class DescriptorProto : IDescriptorProto<MessageOptions> { } + public partial class EnumDescriptorProto : IDescriptorProto<EnumOptions> { } + public partial class EnumValueDescriptorProto : IDescriptorProto<EnumValueOptions> { } + public partial class FieldDescriptorProto : IDescriptorProto<FieldOptions> { } + public partial class FileDescriptorProto : IDescriptorProto<FileOptions> { } + public partial class MethodDescriptorProto : IDescriptorProto<MethodOptions> { } + public partial class ServiceDescriptorProto : IDescriptorProto<ServiceOptions> { } +} diff --git a/src/ProtocolBuffers/Descriptors/DescriptorBase.cs b/src/ProtocolBuffers/Descriptors/DescriptorBase.cs new file mode 100644 index 00000000..0c1414ae --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/DescriptorBase.cs @@ -0,0 +1,83 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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 readonly 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; + } + + 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; } + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/DescriptorPool.cs b/src/ProtocolBuffers/Descriptors/DescriptorPool.cs new file mode 100644 index 00000000..19a5b6a7 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/DescriptorPool.cs @@ -0,0 +1,281 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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 + "\"."); + } + } + // TODO(jonskeet): Check issue 25 wrt the ordering of these parameters + descriptorsByName[fullName] = new PackageDescriptor(fullName, name, 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]*$", RegexOptions.Compiled); + + /// <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; + } + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs b/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs new file mode 100644 index 00000000..c945616d --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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); + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs b/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs new file mode 100644 index 00000000..62c723f3 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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; + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs new file mode 100644 index 00000000..576051ab --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs @@ -0,0 +1,76 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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> { + + 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> + /// Finds an enum value by number. If multiple enum values have the + /// same number, this returns the first defined value with that number. + /// </summary> + internal EnumValueDescriptor FindValueByNumber(int number) { + return File.DescriptorPool.FindEnumValueByNumber(this, 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> + internal EnumValueDescriptor FindValueByName(string name) { + return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name); + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs b/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs new file mode 100644 index 00000000..112a7fb6 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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> { + + 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; } + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs b/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs new file mode 100644 index 00000000..0cd552e4 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs @@ -0,0 +1,437 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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> { + + private readonly MessageDescriptor extensionScope; + private EnumDescriptor enumType; + private MessageDescriptor messageType; + private MessageDescriptor containingType; + private object defaultValue; + private FieldType fieldType; + private MappedType mappedType; + + 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); + } + + /// <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; } + } + + /// <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> + /// 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 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> + /// 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 = float.Parse(Proto.DefaultValue); + break; + case FieldType.Double: + defaultValue = double.Parse(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."); + } + } + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs b/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs new file mode 100644 index 00000000..18f88a31 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs @@ -0,0 +1,34 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; + +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> + [AttributeUsage(AttributeTargets.Field)] + internal sealed class FieldMappingAttribute : Attribute { + internal FieldMappingAttribute(MappedType mappedType, WireFormat.WireType wireType) { + MappedType = mappedType; + WireType = wireType; + } + + internal MappedType MappedType { get; private set; } + internal WireFormat.WireType WireType { get; private set; } + } +} diff --git a/src/ProtocolBuffers/Descriptors/FieldType.cs b/src/ProtocolBuffers/Descriptors/FieldType.cs new file mode 100644 index 00000000..7c15c0cc --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/FieldType.cs @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +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 + } +} diff --git a/src/ProtocolBuffers/Descriptors/FileDescriptor.cs b/src/ProtocolBuffers/Descriptors/FileDescriptor.cs new file mode 100644 index 00000000..abd54e76 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/FileDescriptor.cs @@ -0,0 +1,246 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Google.ProtocolBuffers.DescriptorProtos; + +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 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 DescriptorPool pool; + + 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)); + } + + /// <value> + /// The descriptor in its protocol message representation. + /// </value> + public FileDescriptorProto Proto { + get { return proto; } + } + + /// <value> + /// The <see cref="FileOptions" /> defined in <c>descriptor.proto</c>. + /// </value> + public FileOptions Options { + get { return proto.Options; } + } + + /// <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 BuilderFrom except that the FileDescriptorProto is encoded in + /// protocol buffer wire format. + /// </summary> + public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, + FileDescriptor[] dependencies) { + FileDescriptorProto proto = FileDescriptorProto.ParseFrom(descriptorData); + return BuildFrom(proto, dependencies); + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/IDescriptor.cs b/src/ProtocolBuffers/Descriptors/IDescriptor.cs new file mode 100644 index 00000000..2143f39a --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/IDescriptor.cs @@ -0,0 +1,37 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +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; } + } +} diff --git a/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs b/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs new file mode 100644 index 00000000..d04d40db --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs @@ -0,0 +1,45 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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; } + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/MappedType.cs b/src/ProtocolBuffers/Descriptors/MappedType.cs new file mode 100644 index 00000000..ca7a7b43 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/MappedType.cs @@ -0,0 +1,34 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +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 + } +} diff --git a/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs b/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs new file mode 100644 index 00000000..f387a325 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs @@ -0,0 +1,186 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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)); + + 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 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 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; + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs b/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs new file mode 100644 index 00000000..13e6d141 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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; + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs b/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs new file mode 100644 index 00000000..9884c4a6 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +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; } + } + } +} diff --git a/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs b/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs new file mode 100644 index 00000000..cb152637 --- /dev/null +++ b/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +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(); + } + } + } +} diff --git a/src/ProtocolBuffers/DynamicMessage.cs b/src/ProtocolBuffers/DynamicMessage.cs new file mode 100644 index 00000000..c05a274b --- /dev/null +++ b/src/ProtocolBuffers/DynamicMessage.cs @@ -0,0 +1,414 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using System.IO; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// An implementation of IMessage that can represent arbitrary types, given a MessageaDescriptor. + /// </summary> + public sealed class DynamicMessage : AbstractMessage<DynamicMessage, DynamicMessage.Builder> { + + private readonly MessageDescriptor type; + private readonly FieldSet fields; + private readonly UnknownFieldSet unknownFields; + private int memoizedSize = -1; + + /// <summary> + /// Creates a DynamicMessage with the given FieldSet. + /// </summary> + /// <param name="type"></param> + /// <param name="fields"></param> + /// <param name="unknownFields"></param> + private DynamicMessage(MessageDescriptor type, FieldSet fields, UnknownFieldSet unknownFields) { + this.type = type; + this.fields = fields; + this.unknownFields = unknownFields; + } + + /// <summary> + /// Returns a DynamicMessage representing the default instance of the given type. + /// </summary> + /// <param name="type"></param> + /// <returns></returns> + public static DynamicMessage GetDefaultInstance(MessageDescriptor type) { + return new DynamicMessage(type, FieldSet.DefaultInstance, UnknownFieldSet.DefaultInstance); + } + + /// <summary> + /// Parses a message of the given type from the given stream. + /// </summary> + public static DynamicMessage ParseFrom(MessageDescriptor type, CodedInputStream input) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(input); + return dynamicBuilder.BuildParsed(); + + } + + /// <summary> + /// Parse a message of the given type from the given stream and extension registry. + /// </summary> + /// <param name="type"></param> + /// <param name="input"></param> + /// <param name="extensionRegistry"></param> + /// <returns></returns> + public static DynamicMessage ParseFrom(MessageDescriptor type, CodedInputStream input, ExtensionRegistry extensionRegistry) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(input, extensionRegistry); + return dynamicBuilder.BuildParsed(); + } + + /// <summary> + /// Parses a message of the given type from the given stream. + /// </summary> + public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(input); + return dynamicBuilder.BuildParsed(); + } + + /// <summary> + /// Parse a message of the given type from the given stream and extension registry. + /// </summary> + /// <param name="type"></param> + /// <param name="input"></param> + /// <param name="extensionRegistry"></param> + /// <returns></returns> + public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input, ExtensionRegistry extensionRegistry) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(input, extensionRegistry); + return dynamicBuilder.BuildParsed(); + } + + /// <summary> + /// Parse <paramref name="data"/> as a message of the given type and return it. + /// </summary> + public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(data); + return dynamicBuilder.BuildParsed(); + } + + /// <summary> + /// Parse <paramref name="data"/> as a message of the given type and return it. + /// </summary> + public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data, ExtensionRegistry extensionRegistry) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(data, extensionRegistry); + return dynamicBuilder.BuildParsed(); + + } + + /// <summary> + /// Parse <paramref name="data"/> as a message of the given type and return it. + /// </summary> + public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(data); + return dynamicBuilder.BuildParsed(); + } + + /// <summary> + /// Parse <paramref name="data"/> as a message of the given type and return it. + /// </summary> + public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data, ExtensionRegistry extensionRegistry) { + Builder builder = CreateBuilder(type); + Builder dynamicBuilder = builder.MergeFrom(data, extensionRegistry); + return dynamicBuilder.BuildParsed(); + } + + /// <summary> + /// Constructs a builder for the given type. + /// </summary> + public static Builder CreateBuilder(MessageDescriptor type) { + return new Builder(type); + } + + /// <summary> + /// Constructs a builder for a message of the same type as <paramref name="prototype"/>, + /// and initializes it with the same contents. + /// </summary> + /// <param name="prototype"></param> + /// <returns></returns> + public static Builder CreateBuilder(IMessage prototype) { + return new Builder(prototype.DescriptorForType).MergeFrom(prototype); + } + + // ----------------------------------------------------------------- + // Implementation of IMessage interface. + + public override MessageDescriptor DescriptorForType { + get { return type; } + } + + public override DynamicMessage DefaultInstanceForType { + get { return GetDefaultInstance(type); } + } + + public override IDictionary<FieldDescriptor, object> AllFields { + get { return fields.AllFields; } + } + + public override bool HasField(FieldDescriptor field) { + VerifyContainingType(field); + return fields.HasField(field); + } + + public override object this[FieldDescriptor field] { + get { + VerifyContainingType(field); + object result = fields[field]; + if (result == null) { + result = GetDefaultInstance(field.MessageType); + } + return result; + } + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + VerifyContainingType(field); + return fields.GetRepeatedFieldCount(field); + } + + public override object this[FieldDescriptor field, int index] { + get { + VerifyContainingType(field); + return fields[field, index]; + } + } + + public override UnknownFieldSet UnknownFields { + get { return unknownFields; } + } + + public bool Initialized { + get { return fields.IsInitializedWithRespectTo(type); } + } + + public override void WriteTo(CodedOutputStream output) { + fields.WriteTo(output); + if (type.Options.MessageSetWireFormat) { + unknownFields.WriteAsMessageSetTo(output); + } else { + unknownFields.WriteTo(output); + } + } + + public override int SerializedSize { + get { + int size = memoizedSize; + if (size != -1) return size; + + size = fields.SerializedSize; + if (type.Options.MessageSetWireFormat) { + size += unknownFields.SerializedSizeAsMessageSet; + } else { + size += unknownFields.SerializedSize; + } + + memoizedSize = size; + return size; + } + } + + public override Builder CreateBuilderForType() { + return new Builder(type); + } + + /// <summary> + /// Verifies that the field is a field of this message. + /// </summary> + private void VerifyContainingType(FieldDescriptor field) { + if (field.ContainingType != type) { + throw new ArgumentException("FieldDescriptor does not match message type."); + } + } + + /// <summary> + /// Builder for dynamic messages. Instances are created with DynamicMessage.CreateBuilder. + /// </summary> + public sealed class Builder : AbstractBuilder<DynamicMessage, Builder> { + private readonly MessageDescriptor type; + private FieldSet fields; + private UnknownFieldSet unknownFields; + + internal Builder(MessageDescriptor type) { + this.type = type; + this.fields = FieldSet.CreateInstance(); + this.unknownFields = UnknownFieldSet.DefaultInstance; + } + + protected override Builder ThisBuilder { + get { return this; } + } + + public override Builder Clear() { + fields.Clear(); + return this; + } + + public override Builder MergeFrom(IMessage other) { + if (other.DescriptorForType != type) { + throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type."); + } + fields.MergeFrom(other); + return this; + } + + public override Builder MergeFrom(DynamicMessage other) { + if (other.DescriptorForType != type) { + throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type."); + } + fields.MergeFrom(other); + return this; + } + + public override DynamicMessage Build() { + if (!IsInitialized) { + throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)); + } + return BuildPartial(); + } + + /// <summary> + /// Helper for DynamicMessage.ParseFrom() methods to call. Throws + /// InvalidProtocolBufferException + /// </summary> + /// <returns></returns> + internal DynamicMessage BuildParsed() { + if (!IsInitialized) { + throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)).AsInvalidProtocolBufferException(); + } + return BuildPartial(); + } + + public override DynamicMessage BuildPartial() { + fields.MakeImmutable(); + DynamicMessage result = new DynamicMessage(type, fields, unknownFields); + fields = null; + unknownFields = null; + return result; + } + + public override Builder Clone() { + Builder result = new Builder(type); + result.fields.MergeFrom(fields); + return result; + } + + public override bool IsInitialized { + get { return fields.IsInitializedWithRespectTo(type); } + } + + public override Builder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) { + UnknownFieldSet.Builder unknownFieldsBuilder = UnknownFieldSet.CreateBuilder(unknownFields); + unknownFieldsBuilder.MergeFrom(input, extensionRegistry, this); + unknownFields = unknownFieldsBuilder.Build(); + return this; + } + + public override MessageDescriptor DescriptorForType { + get { return type; } + } + + public override DynamicMessage DefaultInstanceForType { + get { return GetDefaultInstance(type); } + } + + public override IDictionary<FieldDescriptor, object> AllFields { + get { return fields.AllFields; } + } + + public override IBuilder CreateBuilderForField(FieldDescriptor field) { + VerifyContainingType(field); + if (field.MappedType != MappedType.Message) { + throw new ArgumentException("CreateBuilderForField is only valid for fields with message type."); + } + return new Builder(field.MessageType); + } + + public override bool HasField(FieldDescriptor field) { + VerifyContainingType(field); + return fields.HasField(field); + } + + public override object this[FieldDescriptor field, int index] { + get { + VerifyContainingType(field); + return fields[field, index]; + } + set { + VerifyContainingType(field); + fields[field, index] = value; + } + } + + public override object this[FieldDescriptor field] { + get { + VerifyContainingType(field); + object result = fields[field]; + if (result == null) { + result = GetDefaultInstance(field.MessageType); + } + return result; + } + set { + VerifyContainingType(field); + fields[field] = value; + } + } + + public override Builder ClearField(FieldDescriptor field) { + VerifyContainingType(field); + fields.ClearField(field); + return this; + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + VerifyContainingType(field); + return fields.GetRepeatedFieldCount(field); + } + + public override Builder AddRepeatedField(FieldDescriptor field, object value) { + VerifyContainingType(field); + fields.AddRepeatedField(field, value); + return this; + } + + public override UnknownFieldSet UnknownFields { + get { + return unknownFields; + } + set { + unknownFields = value; + } + } + + /// <summary> + /// Verifies that the field is a field of this message. + /// </summary> + /// <param name="field"></param> + private void VerifyContainingType(FieldDescriptor field) { + if (field.ContainingType != type) { + throw new ArgumentException("FieldDescriptor does not match message type."); + } + } + } + } +} diff --git a/src/ProtocolBuffers/ExtendableBuilder.cs b/src/ProtocolBuffers/ExtendableBuilder.cs new file mode 100644 index 00000000..6970d7c3 --- /dev/null +++ b/src/ProtocolBuffers/ExtendableBuilder.cs @@ -0,0 +1,154 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.Collections.Generic; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + public abstract class ExtendableBuilder<TMessage, TBuilder> : GeneratedBuilder<TMessage, TBuilder> + where TMessage : ExtendableMessage<TMessage, TBuilder> + where TBuilder : GeneratedBuilder<TMessage, TBuilder> { + + protected ExtendableBuilder() {} + + /// <summary> + /// Checks if a singular extension is present + /// </summary> + public bool HasExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) { + return MessageBeingBuilt.HasExtension(extension); + } + + /// <summary> + /// Returns the number of elements in a repeated extension. + /// </summary> + public int GetExtensionCount<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension) { + return MessageBeingBuilt.GetExtensionCount(extension); + } + + /// <summary> + /// Returns the value of an extension. + /// </summary> + public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) { + return MessageBeingBuilt.GetExtension(extension); + } + + /// <summary> + /// Returns one element of a repeated extension. + /// </summary> + public TExtension GetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index) { + return MessageBeingBuilt.GetExtension(extension, index); + } + + /// <summary> + /// Sets the value of an extension. + /// </summary> + public TBuilder SetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension, TExtension value) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions[extension.Descriptor] = extension.ToReflectionType(value); + return ThisBuilder; + } + + /// <summary> + /// Sets the value of one element of a repeated extension. + /// </summary> + public TBuilder SetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index, TExtension value) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions[extension.Descriptor, index] = extension.SingularToReflectionType(value); + return ThisBuilder; + } + + /// <summary> + /// Appends a value to a repeated extension. + /// </summary> + public ExtendableBuilder<TMessage, TBuilder> AddExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, TExtension value) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions.AddRepeatedField(extension.Descriptor, extension.SingularToReflectionType(value)); + return this; + } + + /// <summary> + /// Clears an extension. + /// </summary> + public ExtendableBuilder<TMessage, TBuilder> ClearExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions.ClearField(extension.Descriptor); + return this; + } + + /// <summary> + /// Called by subclasses to parse an unknown field or an extension. + /// </summary> + /// <returns>true unless the tag is an end-group tag</returns> + protected override bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields, + ExtensionRegistry extensionRegistry, uint tag) { + return unknownFields.MergeFieldFrom(input, extensionRegistry, this, tag); + } + + // --------------------------------------------------------------- + // Reflection + + + public override object this[FieldDescriptor field, int index] { + set { + if (field.IsExtension) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyContainingType(field); + message.Extensions[field, index] = value; + } else { + base[field, index] = value; + } + } + } + + + public override object this[FieldDescriptor field] { + set { + if (field.IsExtension) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyContainingType(field); + message.Extensions[field] = value; + } else { + base[field] = value; + } + } + } + + public override TBuilder ClearField(FieldDescriptor field) { + if (field.IsExtension) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyContainingType(field); + message.Extensions.ClearField(field); + return ThisBuilder; + } else { + return base.ClearField(field); + } + } + + public override TBuilder AddRepeatedField(FieldDescriptor field, object value) { + if (field.IsExtension) { + ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt; + message.VerifyContainingType(field); + message.Extensions.AddRepeatedField(field, value); + return ThisBuilder; + } else { + return base.AddRepeatedField(field, value); + } + } + } +} diff --git a/src/ProtocolBuffers/ExtendableMessage.cs b/src/ProtocolBuffers/ExtendableMessage.cs new file mode 100644 index 00000000..a4a6e17e --- /dev/null +++ b/src/ProtocolBuffers/ExtendableMessage.cs @@ -0,0 +1,200 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + public abstract class ExtendableMessage<TMessage, TBuilder> : GeneratedMessage<TMessage, TBuilder> + where TMessage : GeneratedMessage<TMessage, TBuilder> + where TBuilder : GeneratedBuilder<TMessage, TBuilder> { + + protected ExtendableMessage() {} + private readonly FieldSet extensions = FieldSet.CreateInstance(); + + /// <summary> + /// Access for the builder. + /// </summary> + internal FieldSet Extensions { + get { return extensions; } + } + + /// <summary> + /// Checks if a singular extension is present. + /// </summary> + public bool HasExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) { + return extensions.HasField(extension.Descriptor); + } + + /// <summary> + /// Returns the number of elements in a repeated extension. + /// </summary> + public int GetExtensionCount<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension) { + return extensions.GetRepeatedFieldCount(extension.Descriptor); + } + + /// <summary> + /// Returns the value of an extension. + /// </summary> + public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) { + object value = extensions[extension.Descriptor]; + if (value == null) { + return (TExtension) extension.MessageDefaultInstance; + } else { + return (TExtension) extension.FromReflectionType(value); + } + } + + /// <summary> + /// Returns one element of a repeated extension. + /// </summary> + public TExtension GetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index) { + return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]); + } + + /// <summary> + /// Called to check if all extensions are initialized. + /// </summary> + protected bool ExtensionsAreInitialized { + get { return extensions.IsInitialized; } + } + + public override bool IsInitialized { + get { + return base.IsInitialized && ExtensionsAreInitialized; + } + } + + #region Reflection + public override IDictionary<FieldDescriptor, object> AllFields { + get { + IDictionary<FieldDescriptor, object> result = GetMutableFieldMap(); + foreach(KeyValuePair<FieldDescriptor, object> entry in extensions.AllFields) { + result[entry.Key] = entry.Value; + } + return Dictionaries.AsReadOnly(result); + } + } + + public override bool HasField(FieldDescriptor field) { + if (field.IsExtension) { + VerifyContainingType(field); + return extensions.HasField(field); + } else { + return base.HasField(field); + } + } + + public override object this[FieldDescriptor field] { + get { + if (field.IsExtension) { + VerifyContainingType(field); + object value = extensions[field]; + if (value == null) { + // Lacking an ExtensionRegistry, we have no way to determine the + // extension's real type, so we return a DynamicMessage. + // TODO(jonskeet): Work out what this means + return DynamicMessage.GetDefaultInstance(field.MessageType); + } else { + return value; + } + } else { + return base[field]; + } + } + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + if (field.IsExtension) { + VerifyContainingType(field); + return extensions.GetRepeatedFieldCount(field); + } else { + return base.GetRepeatedFieldCount(field); + } + } + + public override object this[FieldDescriptor field, int index] { + get { + if (field.IsExtension) { + VerifyContainingType(field); + return extensions[field, index]; + } else { + return base[field, index]; + } + } + } + + internal void VerifyContainingType(FieldDescriptor field) { + if (field.ContainingType != DescriptorForType) { + throw new ArgumentException("FieldDescriptor does not match message type."); + } + } + #endregion + + /// <summary> + /// Used by subclasses to serialize extensions. Extension ranges may be + /// interleaves with field numbers, but we must write them in canonical + /// (sorted by field number) order. This class helps us to write individual + /// ranges of extensions at once. + /// + /// TODO(jonskeet): See if we can improve this in terms of readability. + /// </summary> + protected class ExtensionWriter { + readonly IEnumerator<KeyValuePair<FieldDescriptor, object>> iterator; + readonly FieldSet extensions; + KeyValuePair<FieldDescriptor, object>? next = null; + + internal ExtensionWriter(ExtendableMessage<TMessage, TBuilder> message) { + extensions = message.extensions; + iterator = message.extensions.GetEnumerator(); + if (iterator.MoveNext()) { + next = iterator.Current; + } + } + + public void WriteUntil(int end, CodedOutputStream output) { + while (next != null && next.Value.Key.FieldNumber < end) { + extensions.WriteField(next.Value.Key, next.Value.Value, output); + if (iterator.MoveNext()) { + next = iterator.Current; + } else { + next = null; + } + } + } + } + + protected ExtensionWriter CreateExtensionWriter(ExtendableMessage<TMessage, TBuilder> message) { + return new ExtensionWriter(message); + } + + /// <summary> + /// Called by subclasses to compute the size of extensions. + /// </summary> + protected int ExtensionsSerializedSize { + get { return extensions.SerializedSize; } + } + + internal void VerifyExtensionContainingType<TExtension>(GeneratedExtensionBase<TExtension> extension) { + if (extension.Descriptor.ContainingType != DescriptorForType) { + // This can only happen if someone uses unchecked operations. + throw new ArgumentException("Extension is for type \"" + extension.Descriptor.ContainingType.FullName + + "\" which does not match message type \"" + DescriptorForType.FullName + "\"."); + } + } + } +} diff --git a/src/ProtocolBuffers/ExtensionInfo.cs b/src/ProtocolBuffers/ExtensionInfo.cs new file mode 100644 index 00000000..00cf0d00 --- /dev/null +++ b/src/ProtocolBuffers/ExtensionInfo.cs @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers +{ + public sealed class ExtensionInfo { + /// <summary> + /// The extension's descriptor + /// </summary> + public FieldDescriptor Descriptor { get; private set; } + + /// <summary> + /// A default instance of the extensions's type, if it has a message type, + /// or null otherwise. + /// </summary> + public IMessage DefaultInstance { get; private set; } + + internal ExtensionInfo(FieldDescriptor descriptor) : this(descriptor, null) { + } + + internal ExtensionInfo(FieldDescriptor descriptor, IMessage defaultInstance) { + Descriptor = descriptor; + DefaultInstance = defaultInstance; + } + } +}
\ No newline at end of file diff --git a/src/ProtocolBuffers/ExtensionRegistry.cs b/src/ProtocolBuffers/ExtensionRegistry.cs new file mode 100644 index 00000000..dec75733 --- /dev/null +++ b/src/ProtocolBuffers/ExtensionRegistry.cs @@ -0,0 +1,226 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.Collections.Generic; +using Google.ProtocolBuffers.Descriptors; +using System; + +namespace Google.ProtocolBuffers { + /// <summary> + /// A table of known extensions, searchable by name or field number. When + /// parsing a protocol message that might have extensions, you must provide + /// an <see cref="ExtensionRegistry"/> in which you have registered any extensions + /// that you want to be able to parse. Otherwise, those extensions will just + /// be treated like unknown fields. + /// </summary> + /// <example> + /// For example, if you had the <c>.proto</c> file: + /// <code> + /// option java_class = "MyProto"; + /// + /// message Foo { + /// extensions 1000 to max; + /// } + /// + /// extend Foo { + /// optional int32 bar; + /// } + /// </code> + /// + /// Then you might write code like: + /// + /// <code> + /// ExtensionRegistry registry = ExtensionRegistry.CreateInstance(); + /// registry.Add(MyProto.Bar); + /// MyProto.Foo message = MyProto.Foo.ParseFrom(input, registry); + /// </code> + /// </example> + /// + /// <remarks> + /// <para>You might wonder why this is necessary. Two alternatives might come to + /// mind. First, you might imagine a system where generated extensions are + /// automatically registered when their containing classes are loaded. This + /// is a popular technique, but is bad design; among other things, it creates a + /// situation where behavior can change depending on what classes happen to be + /// loaded. It also introduces a security vulnerability, because an + /// unprivileged class could cause its code to be called unexpectedly from a + /// privileged class by registering itself as an extension of the right type. + /// </para> + /// <para>Another option you might consider is lazy parsing: do not parse an + /// extension until it is first requested, at which point the caller must + /// provide a type to use. This introduces a different set of problems. First, + /// it would require a mutex lock any time an extension was accessed, which + /// would be slow. Second, corrupt data would not be detected until first + /// access, at which point it would be much harder to deal with it. Third, it + /// could violate the expectation that message objects are immutable, since the + /// type provided could be any arbitrary message class. An unprivileged user + /// could take advantage of this to inject a mutable object into a message + /// belonging to privileged code and create mischief.</para> + /// </remarks> + public sealed class ExtensionRegistry { + + private static readonly ExtensionRegistry empty = new ExtensionRegistry( + new Dictionary<string, ExtensionInfo>(), + new Dictionary<DescriptorIntPair, ExtensionInfo>(), + true); + + private readonly IDictionary<string, ExtensionInfo> extensionsByName; + private readonly IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber; + private readonly bool readOnly; + + private ExtensionRegistry(IDictionary<String, ExtensionInfo> extensionsByName, + IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber, + bool readOnly) { + this.extensionsByName = extensionsByName; + this.extensionsByNumber = extensionsByNumber; + this.readOnly = readOnly; + } + + /// <summary> + /// Construct a new, empty instance. + /// </summary> + public static ExtensionRegistry CreateInstance() { + return new ExtensionRegistry(new Dictionary<string, ExtensionInfo>(), + new Dictionary<DescriptorIntPair, ExtensionInfo>(), false); + } + + /// <summary> + /// Get the unmodifiable singleton empty instance. + /// </summary> + public static ExtensionRegistry Empty { + get { return empty; } + } + + public ExtensionRegistry AsReadOnly() { + return new ExtensionRegistry(extensionsByName, extensionsByNumber, true); + } + + /// <summary> + /// Finds an extension by fully-qualified field name, in the + /// proto namespace, i.e. result.Descriptor.FullName will match + /// <paramref name="fullName"/> if a match is found. A null + /// reference is returned if the extension can't be found. + /// </summary> + public ExtensionInfo this[string fullName] { + get { + ExtensionInfo ret; + extensionsByName.TryGetValue(fullName, out ret); + return ret; + } + } + + /// <summary> + /// Finds an extension by containing type and field number. + /// A null reference is returned if the extension can't be found. + /// </summary> + public ExtensionInfo this[MessageDescriptor containingType, int fieldNumber] { + get { + ExtensionInfo ret; + extensionsByNumber.TryGetValue(new DescriptorIntPair(containingType, fieldNumber), out ret); + return ret; + } + } + + /// <summary> + /// Add an extension from a generated file to the registry. + /// </summary> + public void Add<TExtension> (GeneratedExtensionBase<TExtension> extension) { + if (extension.Descriptor.MappedType == MappedType.Message) { + Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance)); + } else { + Add(new ExtensionInfo(extension.Descriptor, null)); + } + } + + /// <summary> + /// Adds a non-message-type extension to the registry by descriptor. + /// </summary> + /// <param name="type"></param> + public void Add(FieldDescriptor type) { + if (type.MappedType == MappedType.Message) { + throw new ArgumentException("ExtensionRegistry.Add() must be provided a default instance " + + "when adding an embedded message extension."); + } + Add(new ExtensionInfo(type, null)); + } + + /// <summary> + /// Adds a message-type-extension to the registry by descriptor. + /// </summary> + /// <param name="type"></param> + /// <param name="defaultInstance"></param> + public void Add(FieldDescriptor type, IMessage defaultInstance) { + if (type.MappedType != MappedType.Message) { + throw new ArgumentException("ExtensionRegistry.Add() provided a default instance for a " + + "non-message extension."); + } + Add(new ExtensionInfo(type, defaultInstance)); + } + + private void Add(ExtensionInfo extension) { + if (readOnly) { + throw new InvalidOperationException("Cannot add entries to a read-only extension registry"); + } + if (!extension.Descriptor.IsExtension) { + throw new ArgumentException("ExtensionRegistry.add() was given a FieldDescriptor for a " + + "regular (non-extension) field."); + } + + extensionsByName[extension.Descriptor.FullName] = extension; + extensionsByNumber[new DescriptorIntPair(extension.Descriptor.ContainingType, + extension.Descriptor.FieldNumber)] = extension; + + FieldDescriptor field = extension.Descriptor; + if (field.ContainingType.Options.MessageSetWireFormat + && field.FieldType == FieldType.Message + && field.IsOptional + && field.ExtensionScope == field.MessageType) { + // This is an extension of a MessageSet type defined within the extension + // type's own scope. For backwards-compatibility, allow it to be looked + // up by type name. + extensionsByName[field.MessageType.FullName] = extension; + } + } + + /// <summary> + /// Nested type just used to represent a pair of MessageDescriptor and int, as + /// the key into the "by number" map. + /// </summary> + private struct DescriptorIntPair : IEquatable<DescriptorIntPair> { + readonly MessageDescriptor descriptor; + readonly int number; + + internal DescriptorIntPair(MessageDescriptor descriptor, int number) { + this.descriptor = descriptor; + this.number = number; + } + + public override int GetHashCode() { + return descriptor.GetHashCode() * ((1 << 16) - 1) + number; + } + + public override bool Equals(object obj) { + if (!(obj is DescriptorIntPair)) { + return false; + } + return Equals((DescriptorIntPair)obj); + } + + public bool Equals(DescriptorIntPair other) { + return descriptor == other.descriptor && number == other.number; + } + } + } +} diff --git a/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs new file mode 100644 index 00000000..c7f5da6d --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs @@ -0,0 +1,84 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers.FieldAccess { + /// <summary> + /// Provides access to fields in generated messages via reflection. + /// This type is public to allow it to be used by generated messages, which + /// create appropriate instances in the .proto file description class. + /// TODO(jonskeet): See if we can hide it somewhere... + /// </summary> + public sealed class FieldAccessorTable<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + readonly IFieldAccessor<TMessage, TBuilder>[] accessors; + + readonly MessageDescriptor descriptor; + + public MessageDescriptor Descriptor { + get { return descriptor; } + } + + /// <summary> + /// Constructs a FieldAccessorTable for a particular message class. + /// Only one FieldAccessorTable should be constructed per class. + /// </summary> + /// <param name="descriptor">The type's descriptor</param> + /// <param name="propertyNames">The Pascal-case names of all the field-based properties in the message.</param> + public FieldAccessorTable(MessageDescriptor descriptor, String[] propertyNames) { + this.descriptor = descriptor; + accessors = new IFieldAccessor<TMessage, TBuilder>[descriptor.Fields.Count]; + for (int i=0; i < accessors.Length; i++) { + accessors[i] = CreateAccessor(descriptor.Fields[i], propertyNames[i]); + } + } + + /// <summary> + /// Creates an accessor for a single field + /// </summary> + private static IFieldAccessor<TMessage, TBuilder> CreateAccessor(FieldDescriptor field, string name) { + if (field.IsRepeated) { + switch (field.MappedType) { + case MappedType.Message: return new RepeatedMessageAccessor<TMessage, TBuilder>(name); + case MappedType.Enum: return new RepeatedEnumAccessor<TMessage, TBuilder>(field, name); + default: return new RepeatedPrimitiveAccessor<TMessage, TBuilder>(name); + } + } else { + switch (field.MappedType) { + case MappedType.Message: return new SingleMessageAccessor<TMessage, TBuilder>(name); + case MappedType.Enum: return new SingleEnumAccessor<TMessage, TBuilder>(field, name); + default: return new SinglePrimitiveAccessor<TMessage, TBuilder>(name); + } + } + } + + internal IFieldAccessor<TMessage, TBuilder> this[FieldDescriptor field] { + get { + if (field.ContainingType != descriptor) { + 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]; + } + } + } +} diff --git a/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs b/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs new file mode 100644 index 00000000..ec079f92 --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs @@ -0,0 +1,75 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Google.ProtocolBuffers.FieldAccess { + + /// <summary> + /// Allows fields to be reflectively accessed in a smart manner. + /// The property descriptors for each field are created once and then cached. + /// In addition, this interface holds knowledge of repeated fields, builders etc. + /// </summary> + internal interface IFieldAccessor<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + /// <summary> + /// Indicates whether the specified message contains the field. + /// </summary> + bool Has(TMessage message); + + /// <summary> + /// Gets the count of the repeated field in the specified message. + /// </summary> + int GetRepeatedCount(TMessage message); + + /// <summary> + /// Clears the field in the specified builder. + /// </summary> + /// <param name="builder"></param> + void Clear(TBuilder builder); + + /// <summary> + /// Creates a builder for the type of this field (which must be a message field). + /// </summary> + IBuilder CreateBuilder(); + + /// <summary> + /// Accessor for single fields + /// </summary> + object GetValue(TMessage message); + /// <summary> + /// Mutator for single fields + /// </summary> + void SetValue(TBuilder builder, object value); + + /// <summary> + /// Accessor for repeated fields + /// </summary> + object GetRepeatedValue(TMessage message, int index); + /// <summary> + /// Mutator for repeated fields + /// </summary> + void SetRepeated(TBuilder builder, int index, object value); + /// <summary> + /// Adds the specified value to the field in the given builder. + /// </summary> + void AddRepeated(TBuilder builder, object value); + /// <summary> + /// Returns a read-only wrapper around the value of a repeated field. + /// </summary> + object GetRepeatedWrapper(TBuilder builder); + } +} diff --git a/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs b/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs new file mode 100644 index 00000000..ddec2229 --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs @@ -0,0 +1,109 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Reflection; + +namespace Google.ProtocolBuffers.FieldAccess { + + /// <summary> + /// The methods in this class are somewhat evil, and should not be tampered with lightly. + /// Basically they allow the creation of relatively weakly typed delegates from MethodInfos + /// which are more strongly typed. They do this by creating an appropriate strongly typed + /// delegate from the MethodInfo, and then calling that within an anonymous method. + /// Mind-bending stuff (at least to your humble narrator) but the resulting delegates are + /// very fast compared with calling Invoke later on. + /// </summary> + internal static class ReflectionUtil { + + /// <summary> + /// Creates a delegate which will execute the given method and then return + /// the result as an object. + /// </summary> + public static Func<T, object> CreateUpcastDelegate<T>(MethodInfo method) { + + // The tricky bit is invoking CreateCreateUpcastDelegateImpl with the right type parameters + MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateUpcastDelegateImpl"); + MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.ReturnType); + return (Func<T, object>) closedImpl.Invoke(null, new object[] { method }); + } + + /// <summary> + /// Method used solely for implementing CreateUpcastDelegate. Public to avoid trust issues + /// in low-trust scenarios, e.g. Silverlight. + /// TODO(jonskeet): Check any of this actually works in Silverlight... + /// </summary> + public static Func<TSource, object> CreateUpcastDelegateImpl<TSource, TResult>(MethodInfo method) { + // Convert the reflection call into an open delegate, i.e. instead of calling x.Method() + // we'll call getter(x). + Func<TSource, TResult> getter = (Func<TSource, TResult>)Delegate.CreateDelegate(typeof(Func<TSource, TResult>), method); + + // Implicit upcast to object (within the delegate) + return delegate(TSource source) { return getter(source); }; + } + + + /// <summary> + /// Creates a delegate which will execute the given method after casting the parameter + /// down from object to the required parameter type. + /// </summary> + public static Action<T, object> CreateDowncastDelegate<T>(MethodInfo method) { + MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateDowncastDelegateImpl"); + MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.GetParameters()[0].ParameterType); + return (Action<T, object>) closedImpl.Invoke(null, new object[] { method }); + } + + public static Action<TSource, object> CreateDowncastDelegateImpl<TSource, TParam>(MethodInfo method) { + // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll + // call Method(x, y) + Action<TSource, TParam> call = (Action<TSource, TParam>) Delegate.CreateDelegate(typeof(Action<TSource, TParam>), method); + + return delegate(TSource source, object parameter) { call(source, (TParam)parameter); }; + } + + /// <summary> + /// Creates a delegate which will execute the given method after casting the parameter + /// down from object to the required parameter type. + /// </summary> + public static Action<T, object> CreateDowncastDelegateIgnoringReturn<T>(MethodInfo method) { + MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateDowncastDelegateIgnoringReturnImpl"); + MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.GetParameters()[0].ParameterType, method.ReturnType); + return (Action<T, object>)closedImpl.Invoke(null, new object[] { method }); + } + + public static Action<TSource, object> CreateDowncastDelegateIgnoringReturnImpl<TSource, TParam, TReturn>(MethodInfo method) { + // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll + // call Method(x, y) + Func<TSource, TParam, TReturn> call = (Func<TSource, TParam, TReturn>) + Delegate.CreateDelegate(typeof(Func<TSource, TParam, TReturn>), method); + + return delegate(TSource source, object parameter) { call(source, (TParam)parameter); }; + } + + /// <summary> + /// Creates a delegate which will execute the given static method and cast the result up to IBuilder. + /// </summary> + public static Func<IBuilder> CreateStaticUpcastDelegate(MethodInfo method) { + MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateStaticUpcastDelegateImpl"); + MethodInfo closedImpl = openImpl.MakeGenericMethod(method.ReturnType); + return (Func<IBuilder>)closedImpl.Invoke(null, new object[] { method }); + } + + public static Func<IBuilder> CreateStaticUpcastDelegateImpl<T>(MethodInfo method) { + Func<T> call = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), method); + return delegate { return (IBuilder)call(); }; + } + } +} diff --git a/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs b/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs new file mode 100644 index 00000000..f00f7ee2 --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; +using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers.FieldAccess { + + /// <summary> + /// Accessor for a repeated enum field. + /// </summary> + internal sealed class RepeatedEnumAccessor<TMessage, TBuilder> : RepeatedPrimitiveAccessor<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + private readonly EnumDescriptor enumDescriptor; + + internal RepeatedEnumAccessor(FieldDescriptor field, string name) : base(name) { + enumDescriptor = field.EnumType; + } + + public override object GetValue(TMessage message) { + List<EnumValueDescriptor> ret = new List<EnumValueDescriptor>(); + foreach (int rawValue in (IEnumerable) base.GetValue(message)) { + ret.Add(enumDescriptor.FindValueByNumber(rawValue)); + } + return Lists.AsReadOnly(ret); + } + + public override object GetRepeatedValue(TMessage message, int index) { + // Note: This relies on the fact that the CLR allows unboxing from an enum to + // its underlying value + int rawValue = (int) base.GetRepeatedValue(message, index); + return enumDescriptor.FindValueByNumber(rawValue); + } + + public override void AddRepeated(TBuilder builder, object value) { + base.AddRepeated(builder, ((EnumValueDescriptor) value).Number); + } + + public override void SetRepeated(TBuilder builder, int index, object value) { + base.SetRepeated(builder, index, ((EnumValueDescriptor) value).Number); + } + } +} diff --git a/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs b/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs new file mode 100644 index 00000000..35d7b1a8 --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs @@ -0,0 +1,74 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Reflection; + +namespace Google.ProtocolBuffers.FieldAccess { + + /// <summary> + /// Accessor for a repeated message field. + /// + /// TODO(jonskeet): Try to extract the commonality between this and SingleMessageAccessor. + /// We almost want multiple inheritance... + /// </summary> + internal sealed class RepeatedMessageAccessor<TMessage, TBuilder> : RepeatedPrimitiveAccessor<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + /// <summary> + /// The static method to create a builder for the property type. For example, + /// in a message type "Foo", a field called "bar" might be of type "Baz". This + /// method is Baz.CreateBuilder. + /// </summary> + private readonly Func<IBuilder> createBuilderDelegate; + + internal RepeatedMessageAccessor(string name) : base(name) { + MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", Type.EmptyTypes); + if (createBuilderMethod == null) { + throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name); + } + createBuilderDelegate = ReflectionUtil.CreateStaticUpcastDelegate(createBuilderMethod); + } + + /// <summary> + /// Creates a message of the appropriate CLR type from the given value, + /// which may already be of the right type or may be a dynamic message. + /// </summary> + private object CoerceType(object value) { + + // If it's already of the right type, we're done + if (ClrType.IsInstanceOfType(value)) { + return value; + } + + // No... so let's create a builder of the right type, and merge the value in. + IMessage message = (IMessage) value; + return CreateBuilder().WeakMergeFrom(message).WeakBuild(); + } + + public override void SetRepeated(TBuilder builder, int index, object value) { + base.SetRepeated(builder, index, CoerceType(value)); + } + + public override IBuilder CreateBuilder() { + return createBuilderDelegate(); + } + + public override void AddRepeated(TBuilder builder, object value) { + base.AddRepeated(builder, CoerceType(value)); + } + } +} diff --git a/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs b/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs new file mode 100644 index 00000000..35a2a204 --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs @@ -0,0 +1,124 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Reflection; + +namespace Google.ProtocolBuffers.FieldAccess { + /// <summary> + /// Accesor for a repeated field of type int, ByteString etc. + /// </summary> + internal class RepeatedPrimitiveAccessor<TMessage, TBuilder> : IFieldAccessor<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + private readonly Type clrType; + private readonly Func<TMessage, object> getValueDelegate; + private readonly Func<TBuilder, IBuilder> clearDelegate; + private readonly Action<TBuilder, object> addValueDelegate; + private readonly Func<TBuilder, object> getRepeatedWrapperDelegate; + private readonly Func<TMessage, int> countDelegate; + private readonly MethodInfo getElementMethod; + private readonly MethodInfo setElementMethod; + + + /// <summary> + /// The CLR type of the field (int, the enum type, ByteString, the message etc). + /// This is taken from the return type of the method used to retrieve a single + /// value. + /// </summary> + protected Type ClrType { + get { return clrType; } + } + + internal RepeatedPrimitiveAccessor(string name) { + PropertyInfo messageProperty = typeof(TMessage).GetProperty(name + "List"); + PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name + "List"); + PropertyInfo countProperty = typeof(TMessage).GetProperty(name + "Count"); + MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, Type.EmptyTypes); + getElementMethod = typeof(TMessage).GetMethod("Get" + name, new Type[] { typeof(int) }); + clrType = getElementMethod.ReturnType; + MethodInfo addMethod = typeof(TBuilder).GetMethod("Add" + name, new Type[] { ClrType }); + setElementMethod = typeof(TBuilder).GetMethod("Set" + name, new Type[] { typeof(int), ClrType }); + if (messageProperty == null + || builderProperty == null + || countProperty == null + || clearMethod == null + || addMethod == null + || getElementMethod == null + || setElementMethod == null) { + throw new ArgumentException("Not all required properties/methods available"); + } + clearDelegate = (Func<TBuilder, IBuilder>)Delegate.CreateDelegate(typeof(Func<TBuilder, IBuilder>), clearMethod); + countDelegate = (Func<TMessage, int>)Delegate.CreateDelegate + (typeof(Func<TMessage, int>), countProperty.GetGetMethod()); + getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod()); + addValueDelegate = ReflectionUtil.CreateDowncastDelegateIgnoringReturn<TBuilder>(addMethod); + getRepeatedWrapperDelegate = ReflectionUtil.CreateUpcastDelegate<TBuilder>(builderProperty.GetGetMethod()); + } + + public bool Has(TMessage message) { + throw new InvalidOperationException(); + } + + public virtual IBuilder CreateBuilder() { + throw new InvalidOperationException(); + } + + public virtual object GetValue(TMessage message) { + return getValueDelegate(message); + } + + public void SetValue(TBuilder builder, object value) { + // Add all the elements individually. This serves two purposes: + // 1) Verifies that each element has the correct type. + // 2) Insures that the caller cannot modify the list later on and + // have the modifications be reflected in the message. + Clear(builder); + foreach (object element in (IEnumerable) value) { + AddRepeated(builder, element); + } + } + + public void Clear(TBuilder builder) { + clearDelegate(builder); + } + + public int GetRepeatedCount(TMessage message) { + return countDelegate(message); + } + + public virtual object GetRepeatedValue(TMessage message, int index) { + return getElementMethod.Invoke(message, new object[] {index } ); + } + + public virtual void SetRepeated(TBuilder builder, int index, object value) { + setElementMethod.Invoke(builder, new object[] {index, value} ); + } + + public virtual void AddRepeated(TBuilder builder, object value) { + addValueDelegate(builder, value); + } + + /// <summary> + /// The builder class's accessor already builds a read-only wrapper for + /// us, which is exactly what we want. + /// </summary> + public object GetRepeatedWrapper(TBuilder builder) { + return getRepeatedWrapperDelegate(builder); + } + } +}
\ No newline at end of file diff --git a/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs b/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs new file mode 100644 index 00000000..eb28160a --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs @@ -0,0 +1,54 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers.FieldAccess { + /// <summary> + /// Accessor for fields representing a non-repeated enum value. + /// </summary> + internal sealed class SingleEnumAccessor<TMessage, TBuilder> : SinglePrimitiveAccessor<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + private readonly EnumDescriptor enumDescriptor; + + internal SingleEnumAccessor(FieldDescriptor field, string name) : base(name) { + enumDescriptor = field.EnumType; + } + + /// <summary> + /// Returns an EnumValueDescriptor representing the value in the builder. + /// Note that if an enum has multiple values for the same number, the descriptor + /// for the first value with that number will be returned. + /// </summary> + public override object GetValue(TMessage message) { + // Note: This relies on the fact that the CLR allows unboxing from an enum to + // its underlying value + int rawValue = (int) base.GetValue(message); + return enumDescriptor.FindValueByNumber(rawValue); + } + + /// <summary> + /// Sets the value as an enum (via an int) in the builder, + /// from an EnumValueDescriptor parameter. + /// </summary> + public override void SetValue(TBuilder builder, object value) { + EnumValueDescriptor valueDescriptor = (EnumValueDescriptor) value; + base.SetValue(builder, valueDescriptor.Number); + } + } +}
\ No newline at end of file diff --git a/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs new file mode 100644 index 00000000..5aa9f777 --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs @@ -0,0 +1,66 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Reflection; + +namespace Google.ProtocolBuffers.FieldAccess { + /// <summary> + /// Accessor for fields representing a non-repeated message value. + /// </summary> + internal sealed class SingleMessageAccessor<TMessage, TBuilder> : SinglePrimitiveAccessor<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + /// <summary> + /// The static method to create a builder for the property type. For example, + /// in a message type "Foo", a field called "bar" might be of type "Baz". This + /// method is Baz.CreateBuilder. + /// </summary> + private readonly Func<IBuilder> createBuilderDelegate; + + internal SingleMessageAccessor(string name) : base(name) { + MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", Type.EmptyTypes); + if (createBuilderMethod == null) { + throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name); + } + createBuilderDelegate = ReflectionUtil.CreateStaticUpcastDelegate(createBuilderMethod); + } + + /// <summary> + /// Creates a message of the appropriate CLR type from the given value, + /// which may already be of the right type or may be a dynamic message. + /// </summary> + private object CoerceType(object value) { + + // If it's already of the right type, we're done + if (ClrType.IsInstanceOfType(value)) { + return value; + } + + // No... so let's create a builder of the right type, and merge the value in. + IMessage message = (IMessage) value; + return CreateBuilder().WeakMergeFrom(message).WeakBuild(); + } + + public override void SetValue(TBuilder builder, object value) { + base.SetValue(builder, CoerceType(value)); + } + + public override IBuilder CreateBuilder() { + return createBuilderDelegate(); + } + } +}
\ No newline at end of file diff --git a/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs b/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs new file mode 100644 index 00000000..c10936d4 --- /dev/null +++ b/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs @@ -0,0 +1,104 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Reflection; + +namespace Google.ProtocolBuffers.FieldAccess { + /// <summary> + /// Access for a non-repeated field of a "primitive" type (i.e. not another message or an enum). + /// </summary> + internal class SinglePrimitiveAccessor<TMessage, TBuilder> : IFieldAccessor<TMessage, TBuilder> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + private readonly Type clrType; + private readonly Func<TMessage, object> getValueDelegate; + private readonly Action<TBuilder, object> setValueDelegate; + private readonly Func<TMessage, bool> hasDelegate; + private readonly Func<TBuilder, IBuilder> clearDelegate; + + /// <summary> + /// The CLR type of the field (int, the enum type, ByteString, the message etc). + /// As declared by the property. + /// </summary> + protected Type ClrType { + get { return clrType; } + } + + internal SinglePrimitiveAccessor(string name) { + + string propertyName = name == typeof(TMessage).Name ? name + "_" : name; + PropertyInfo messageProperty = typeof(TMessage).GetProperty(propertyName); + PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name); // FIXME! + if (builderProperty == null) builderProperty = typeof(TBuilder).GetProperty(propertyName); // FIXME! + PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name); + MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, Type.EmptyTypes); + if (messageProperty == null || builderProperty == null || hasProperty == null || clearMethod == null) { + throw new ArgumentException("Not all required properties/methods available"); + } + clrType = messageProperty.PropertyType; + hasDelegate = (Func<TMessage, bool>)Delegate.CreateDelegate(typeof(Func<TMessage, bool>), hasProperty.GetGetMethod()); + clearDelegate = (Func<TBuilder, IBuilder>)Delegate.CreateDelegate(typeof(Func<TBuilder, IBuilder>), clearMethod); + getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod()); + setValueDelegate = ReflectionUtil.CreateDowncastDelegate<TBuilder>(builderProperty.GetSetMethod()); + } + + public bool Has(TMessage message) { + return hasDelegate(message); + } + + public void Clear(TBuilder builder) { + clearDelegate(builder); + } + + /// <summary> + /// Only valid for message types - this implementation throws InvalidOperationException. + /// </summary> + public virtual IBuilder CreateBuilder() { + throw new InvalidOperationException(); + } + + public virtual object GetValue(TMessage message) { + return getValueDelegate(message); + } + + public virtual void SetValue(TBuilder builder, object value) { + setValueDelegate(builder, value); + } + + #region Methods only related to repeated values + public int GetRepeatedCount(TMessage message) { + throw new InvalidOperationException(); + } + + public object GetRepeatedValue(TMessage message, int index) { + throw new InvalidOperationException(); + } + + public void SetRepeated(TBuilder builder, int index, object value) { + throw new InvalidOperationException(); + } + + public void AddRepeated(TBuilder builder, object value) { + throw new InvalidOperationException(); + } + + public object GetRepeatedWrapper(TBuilder builder) { + throw new InvalidOperationException(); + } + #endregion + } +}
\ No newline at end of file diff --git a/src/ProtocolBuffers/FieldSet.cs b/src/ProtocolBuffers/FieldSet.cs new file mode 100644 index 00000000..c130d858 --- /dev/null +++ b/src/ProtocolBuffers/FieldSet.cs @@ -0,0 +1,434 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; +using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + /// <summary> + /// A class which represents an arbitrary set of fields of some message type. + /// This is used to implement DynamicMessage, and also to represent extensions + /// in GeneratedMessage. This class is internal, since outside users should probably + /// be using DynamicMessage. + /// + /// As in the Java implementation, this class goes against the rest of the framework + /// in terms of mutability. Instead of having a mutable Builder class and an immutable + /// FieldSet class, FieldSet just has a MakeImmutable() method. This is safe so long as + /// all callers are careful not to let a mutable FieldSet escape into the open. This would + /// be impossible to guarantee if this were a public class, of course. + /// + /// All repeated fields are stored as IList[object] even + /// TODO(jonskeet): Finish this comment! + /// </summary> + internal sealed class FieldSet { + + private static readonly FieldSet defaultInstance = new FieldSet(new Dictionary<FieldDescriptor, object>()).MakeImmutable(); + + private IDictionary<FieldDescriptor, object> fields; + + private FieldSet(IDictionary<FieldDescriptor, object> fields) { + this.fields = fields; + } + + public static FieldSet CreateInstance() { + // Use SortedList to keep fields in the canonical order + return new FieldSet(new SortedList<FieldDescriptor, object>()); + } + + /// <summary> + /// Makes this FieldSet immutable, and returns it for convenience. Any + /// mutable repeated fields are made immutable, as well as the map itself. + /// </summary> + internal FieldSet MakeImmutable() { + // First check if we have any repeated values + bool hasRepeats = false; + foreach (object value in fields.Values) { + IList<object> list = value as IList<object>; + if (list != null && !list.IsReadOnly) { + hasRepeats = true; + break; + } + } + + if (hasRepeats) { + var tmp = new SortedList<FieldDescriptor, object>(); + foreach (KeyValuePair<FieldDescriptor, object> entry in fields) { + IList<object> list = entry.Value as IList<object>; + tmp[entry.Key] = list == null ? entry.Value : Lists.AsReadOnly(list); + } + fields = tmp; + } + + fields = Dictionaries.AsReadOnly(fields); + + return this; + } + + /// <summary> + /// Returns the default, immutable instance with no fields defined. + /// </summary> + internal static FieldSet DefaultInstance { + get { return defaultInstance; } + } + + /// <summary> + /// Returns an immutable mapping of fields. Note that although the mapping itself + /// is immutable, the entries may not be (i.e. any repeated values are represented by + /// mutable lists). The behaviour is not specified if the contents are mutated. + /// </summary> + internal IDictionary<FieldDescriptor, object> AllFields { + get { return Dictionaries.AsReadOnly(fields); } + } + + /// <summary> + /// See <see cref="IMessage.HasField"/>. + /// </summary> + public bool HasField(FieldDescriptor field) { + if (field.IsRepeated) { + throw new ArgumentException("HasField() can only be called on non-repeated fields."); + } + + return fields.ContainsKey(field); + } + + /// <summary> + /// Clears all fields. + /// </summary> + internal void Clear() { + fields.Clear(); + } + + /// <summary> + /// See <see cref="IMessage.Item(FieldDescriptor)"/> + /// </summary> + /// <remarks> + /// If the field is not set, the behaviour when fetching this property varies by field type: + /// <list> + /// <item>For singular message values, null is returned.</item> + /// <item>For singular non-message values, the default value of the field is returned.</item> + /// <item>For repeated values, an empty immutable list is returned. This will be compatible + /// with IList[object], regardless of the type of the repeated item.</item> + /// </list> + /// This method returns null if the field is a singular message type + /// and is not set; in this case it is up to the caller to fetch the + /// message's default instance. For repeated fields of message types, + /// an empty collection is returned. For repeated fields of non-message + /// types, null is returned. + /// <para /> + /// When setting this property, any list values are copied, and each element is checked + /// to ensure it is of an appropriate type. + /// </remarks> + /// + internal object this[FieldDescriptor field] { + get { + object result; + if (fields.TryGetValue(field, out result)) { + return result; + } + if (field.MappedType == MappedType.Message) { + if (field.IsRepeated) { + return new List<object>(); + } else { + return null; + } + } + return field.DefaultValue; + } + set { + if (field.IsRepeated) { + List<object> list = value as List<object>; + if (list == null) { + throw new ArgumentException("Wrong object type used with protocol message reflection."); + } + + // Wrap the contents in a new list so that the caller cannot change + // the list's contents after setting it. + List<object> newList = new List<object>(list); + foreach (object element in newList) { + VerifyType(field, element); + } + value = newList; + } + else { + VerifyType(field, value); + } + fields[field] = value; + } + } + + /// <summary> + /// See <see cref="IMessage.Item(FieldDescriptor,int)" /> + /// </summary> + internal object this[FieldDescriptor field, int index] { + get { + if (!field.IsRepeated) { + throw new ArgumentException("Indexer specifying field and index can only be called on repeated fields."); + } + + return ((IList<object>) this[field])[index]; + } + set { + if (!field.IsRepeated) { + throw new ArgumentException("Indexer specifying field and index can only be called on repeated fields."); + } + VerifyType(field, value); + object list; + if (!fields.TryGetValue(field, out list)) { + throw new ArgumentOutOfRangeException(); + } + ((IList<object>) list)[index] = value; + } + } + + /// <summary> + /// See <see cref="IBuilder{TMessage, TBuilder}.AddRepeatedField" /> + /// </summary> + internal void AddRepeatedField(FieldDescriptor field, object value) { + if (!field.IsRepeated) { + throw new ArgumentException("AddRepeatedField can only be called on repeated fields."); + } + VerifyType(field, value); + object list; + if (!fields.TryGetValue(field, out list)) { + list = new List<object>(); + fields[field] = list; + } + ((IList<object>) list).Add(value); + } + + /// <summary> + /// Returns an enumerator for the field map. Used to write the fields out. + /// </summary> + internal IEnumerator<KeyValuePair<FieldDescriptor, object>> GetEnumerator() { + return fields.GetEnumerator(); + } + + /// <summary> + /// See <see cref="IMessage.IsInitialized" /> + /// </summary> + /// <remarks> + /// Since FieldSet itself does not have any way of knowing about + /// required fields that aren't actually present in the set, it is up + /// to the caller to check for genuinely required fields. This property + /// merely checks that any messages present are themselves initialized. + /// </remarks> + internal bool IsInitialized { + get { + foreach (KeyValuePair<FieldDescriptor, object> entry in fields) { + FieldDescriptor field = entry.Key; + if (field.MappedType == MappedType.Message) { + if (field.IsRepeated) { + foreach(IMessage message in (IEnumerable) entry.Value) { + if (!message.IsInitialized) { + return false; + } + } + } else { + if (!((IMessage) entry.Value).IsInitialized) { + return false; + } + } + } + } + return true; + } + } + + /// <summary> + /// Verifies whether all the required fields in the specified message + /// descriptor are present in this field set, as well as whether + /// all the embedded messages are themselves initialized. + /// </summary> + internal bool IsInitializedWithRespectTo(MessageDescriptor type) { + foreach (FieldDescriptor field in type.Fields) { + if (field.IsRequired && !HasField(field)) { + return false; + } + } + return IsInitialized; + } + + /// <summary> + /// See <see cref="IBuilder{TMessage, TBuilder}.ClearField" /> + /// </summary> + public void ClearField(FieldDescriptor field) { + fields.Remove(field); + } + + /// <summary> + /// See <see cref="IMessage.GetRepeatedFieldCount" /> + /// </summary> + public int GetRepeatedFieldCount(FieldDescriptor field) { + if (!field.IsRepeated) { + throw new ArgumentException("GetRepeatedFieldCount() can only be called on repeated fields."); + } + + return ((IList<object>) this[field]).Count; + } + + /// <summary> + /// Implementation of both <c>MergeFrom</c> methods. + /// </summary> + /// <param name="otherFields"></param> + private void MergeFields(IEnumerable<KeyValuePair<FieldDescriptor, object>> otherFields) { + // Note: We don't attempt to verify that other's fields have valid + // types. Doing so would be a losing battle. We'd have to verify + // all sub-messages as well, and we'd have to make copies of all of + // them to insure that they don't change after verification (since + // the IMessage interface itself cannot enforce immutability of + // implementations). + // TODO(jonskeet): Provide a function somewhere called MakeDeepCopy() + // which allows people to make secure deep copies of messages. + + foreach (KeyValuePair<FieldDescriptor, object> entry in otherFields) { + FieldDescriptor field = entry.Key; + object existingValue; + fields.TryGetValue(field, out existingValue); + if (field.IsRepeated) { + if (existingValue == null) { + existingValue = new List<object>(); + fields[field] = existingValue; + } + IList<object> list = (IList<object>) existingValue; + foreach (object otherValue in (IEnumerable) entry.Value) { + list.Add(otherValue); + } + } else if (field.MappedType == MappedType.Message && existingValue != null) { + IMessage existingMessage = (IMessage)existingValue; + IMessage merged = existingMessage.WeakCreateBuilderForType() + .WeakMergeFrom(existingMessage) + .WeakMergeFrom((IMessage) entry.Value) + .WeakBuild(); + this[field] = merged; + } else { + this[field] = entry.Value; + } + } + } + + /// <summary> + /// See <see cref="IBuilder{TMessage, TBuilder}.MergeFrom(IMessage)" /> + /// </summary> + public void MergeFrom(IMessage other) { + MergeFields(other.AllFields); + } + + /// <summary> + /// Like <see cref="MergeFrom(IMessage)"/>, but merges from another <c>FieldSet</c>. + /// </summary> + public void MergeFrom(FieldSet other) { + MergeFields(other.fields); + } + + /// <summary> + /// See <see cref="IMessage.WriteTo(CodedOutputStream)" />. + /// </summary> + public void WriteTo(CodedOutputStream output) { + foreach (KeyValuePair<FieldDescriptor, object> entry in fields) { + WriteField(entry.Key, entry.Value, output); + } + } + + /// <summary> + /// Writes a single field to a CodedOutputStream. + /// </summary> + public void WriteField(FieldDescriptor field, Object value, CodedOutputStream output) { + if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) { + output.WriteMessageSetExtension(field.FieldNumber, (IMessage) value); + } else { + if (field.IsRepeated) { + foreach (object element in (IEnumerable) value) { + output.WriteField(field.FieldType, field.FieldNumber, element); + } + } else { + output.WriteField(field.FieldType, field.FieldNumber, value); + } + } + } + + /// <summary> + /// See <see cref="IMessage.SerializedSize" />. It's up to the caller to + /// cache the resulting size if desired. + /// </summary> + public int SerializedSize { + get { + int size = 0; + foreach (KeyValuePair<FieldDescriptor, object> entry in fields) { + FieldDescriptor field = entry.Key; + object value = entry.Value; + + if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) { + size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessage) value); + } else { + if (field.IsRepeated) { + foreach (object element in (IEnumerable) value) { + size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, element); + } + } else { + size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, value); + } + } + } + return size; + } + } + + /// <summary> + /// Verifies that the given object is of the correct type to be a valid + /// value for the given field. + /// </summary> + /// <remarks> + /// For repeated fields, this checks if the object is of the right + /// element type, not whether it's a list. + /// </remarks> + /// <exception cref="ArgumentException">The value is not of the right type.</exception> + private static void VerifyType(FieldDescriptor field, object value) { + bool isValid = false; + switch (field.MappedType) { + case MappedType.Int32: isValid = value is int; break; + case MappedType.Int64: isValid = value is long; break; + case MappedType.UInt32: isValid = value is uint; break; + case MappedType.UInt64: isValid = value is ulong; break; + case MappedType.Single: isValid = value is float; break; + case MappedType.Double: isValid = value is double; break; + case MappedType.Boolean: isValid = value is bool; break; + case MappedType.String: isValid = value is string; break; + case MappedType.ByteString: isValid = value is ByteString; break; + case MappedType.Enum: + EnumValueDescriptor enumValue = value as EnumValueDescriptor; + isValid = enumValue != null && enumValue.EnumDescriptor == field.EnumType; + break; + case MappedType.Message: + IMessage messageValue = value as IMessage; + isValid = messageValue != null && messageValue.DescriptorForType == field.MessageType; + break; + } + + if (!isValid) { + // When chaining calls to SetField(), it can be hard to tell from + // the stack trace which exact call failed, since the whole chain is + // considered one line of code. So, let's make sure to include the + // field name and other useful info in the exception. + throw new ArgumentException("Wrong object type used with protocol message reflection. " + + "Message type \"" + field.ContainingType.FullName + + "\", field \"" + (field.IsExtension ? field.FullName : field.Name) + + "\", value was type \"" + value.GetType().Name + "\"."); + } + } + } +} diff --git a/src/ProtocolBuffers/GeneratedBuilder.cs b/src/ProtocolBuffers/GeneratedBuilder.cs new file mode 100644 index 00000000..4f577a79 --- /dev/null +++ b/src/ProtocolBuffers/GeneratedBuilder.cs @@ -0,0 +1,177 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; +using Google.ProtocolBuffers.Descriptors; +using Google.ProtocolBuffers.FieldAccess; + +namespace Google.ProtocolBuffers { + /// <summary> + /// All generated protocol message builder classes extend this class. It implements + /// most of the IBuilder interface using reflection. Users can ignore this class + /// as an implementation detail. + /// </summary> + public abstract class GeneratedBuilder<TMessage, TBuilder> : AbstractBuilder<TMessage, TBuilder> + where TMessage : GeneratedMessage <TMessage, TBuilder> + where TBuilder : GeneratedBuilder<TMessage, TBuilder> { + + /// <summary> + /// Returns the message being built at the moment. + /// </summary> + protected abstract TMessage MessageBeingBuilt { get; } + + protected internal FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { + get { return MessageBeingBuilt.FieldAccessorsFromBuilder; } + } + + public override bool IsInitialized { + get { return MessageBeingBuilt.IsInitialized; } + } + + public override IDictionary<FieldDescriptor, object> AllFields { + get { return MessageBeingBuilt.AllFields; } + } + + public override object this[FieldDescriptor field] { + get { + // For repeated fields, the underlying list object is still modifiable at this point. + // Make sure not to expose the modifiable list to the caller. + return field.IsRepeated + ? InternalFieldAccessors[field].GetRepeatedWrapper(ThisBuilder) + : MessageBeingBuilt[field]; + } + set { + InternalFieldAccessors[field].SetValue(ThisBuilder, value); + } + } + + /// <summary> + /// Adds all of the specified values to the given collection. + /// </summary> + protected void AddRange<T>(IEnumerable<T> source, IList<T> destination) { + List<T> list = destination as List<T>; + if (list != null) { + list.AddRange(source); + } else { + foreach (T element in source) { + destination.Add(element); + } + } + } + + /// <summary> + /// Called by derived classes to parse an unknown field. + /// </summary> + /// <returns>true unless the tag is an end-group tag</returns> + protected virtual bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields, + ExtensionRegistry extensionRegistry, uint tag) { + return unknownFields.MergeFieldFrom(tag, input); + } + + public override MessageDescriptor DescriptorForType { + get { return MessageBeingBuilt.DescriptorForType; } + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + return MessageBeingBuilt.GetRepeatedFieldCount(field); + } + + public override object this[FieldDescriptor field, int index] { + get { return MessageBeingBuilt[field, index]; } + set { InternalFieldAccessors[field].SetRepeated(ThisBuilder, index, value); } + } + + public override bool HasField(FieldDescriptor field) { + return MessageBeingBuilt.HasField(field); + } + + public override IBuilder CreateBuilderForField(FieldDescriptor field) { + return InternalFieldAccessors[field].CreateBuilder(); + } + + public override TBuilder ClearField(FieldDescriptor field) { + InternalFieldAccessors[field].Clear(ThisBuilder); + return ThisBuilder; + } + + public override TBuilder MergeFrom(TMessage other) { + if (other.DescriptorForType != InternalFieldAccessors.Descriptor) { + throw new ArgumentException("Message type mismatch"); + } + + foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) { + FieldDescriptor field = entry.Key; + if (field.IsRepeated) { + // Concatenate repeated fields + foreach (object element in (IEnumerable)entry.Value) { + AddRepeatedField(field, element); + } + } else if (field.MappedType == MappedType.Message && HasField(field)) { + // Merge singular embedded messages + IMessage oldValue = (IMessage)this[field]; + this[field] = oldValue.WeakCreateBuilderForType() + .WeakMergeFrom(oldValue) + .WeakMergeFrom((IMessage)entry.Value) + .WeakBuildPartial(); + } else { + // Just overwrite + this[field] = entry.Value; + } + } + return ThisBuilder; + } + + public override TBuilder MergeUnknownFields(UnknownFieldSet unknownFields) { + TMessage result = MessageBeingBuilt; + result.SetUnknownFields(UnknownFieldSet.CreateBuilder(result.UnknownFields) + .MergeFrom(unknownFields) + .Build()); + return ThisBuilder; + } + + public override TBuilder AddRepeatedField(FieldDescriptor field, object value) { + InternalFieldAccessors[field].AddRepeated(ThisBuilder, value); + return ThisBuilder; + } + + /// <summary> + /// Like Build(), but will wrap UninitializedMessageException in + /// InvalidProtocolBufferException. + /// </summary> + public TMessage BuildParsed() { + if (!IsInitialized) { + throw new UninitializedMessageException(MessageBeingBuilt).AsInvalidProtocolBufferException(); + } + return BuildPartial(); + } + + /// <summary> + /// Implementation of <see cref="IBuilder{TMessage, TBuilder}.Build" />. + /// </summary> + public override TMessage Build() { + if (!IsInitialized) { + throw new UninitializedMessageException(MessageBeingBuilt); + } + return BuildPartial(); + } + + public override UnknownFieldSet UnknownFields { + get { return MessageBeingBuilt.UnknownFields; } + set { MessageBeingBuilt.SetUnknownFields(value); } + } + } +} diff --git a/src/ProtocolBuffers/GeneratedExtensionBase.cs b/src/ProtocolBuffers/GeneratedExtensionBase.cs new file mode 100644 index 00000000..5d8e2845 --- /dev/null +++ b/src/ProtocolBuffers/GeneratedExtensionBase.cs @@ -0,0 +1,136 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Base type for all generated extensions. + /// </summary> + /// <remarks> + /// The protocol compiler generates a static singleton instance of this + /// class for each extension. For exmaple, imagine a .proto file with: + /// <code> + /// message Foo { + /// extensions 1000 to max + /// } + /// + /// extend Foo { + /// optional int32 bar; + /// } + /// </code> + /// Then MyProto.Foo.Bar has type GeneratedExtensionBase<MyProto.Foo,int>. + /// <para /> + /// In general, users should ignore the details of this type, and + /// simply use the static singletons as parameters to the extension accessors + /// in ExtendableMessage and ExtendableBuilder. + /// The interface implemented by both GeneratedException and GeneratedRepeatException, + /// to make it easier to cope with repeats separately. + /// </remarks> + public abstract class GeneratedExtensionBase<TExtension> { + + private readonly FieldDescriptor descriptor; + private readonly IMessage messageDefaultInstance; + + protected GeneratedExtensionBase(FieldDescriptor descriptor, Type singularExtensionType) { + if (!descriptor.IsExtension) { + throw new ArgumentException("GeneratedExtension given a regular (non-extension) field."); + } + + this.descriptor = descriptor; + if (descriptor.MappedType == MappedType.Message) { + PropertyInfo defaultInstanceProperty = singularExtensionType + .GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public); + if (defaultInstanceProperty == null) { + throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name); + } + messageDefaultInstance = (IMessage)defaultInstanceProperty.GetValue(null, null); + } + } + + public FieldDescriptor Descriptor { + get { return descriptor; } + } + + /// <summary> + /// Returns the default message instance for extensions which are message types. + /// </summary> + public IMessage MessageDefaultInstance { + get { return messageDefaultInstance; } + } + + public object SingularFromReflectionType(object value) { + switch (Descriptor.MappedType) { + case MappedType.Message: + if (value is TExtension) { + return value; + } else { + // It seems the copy of the embedded message stored inside the + // extended message is not of the exact type the user was + // expecting. This can happen if a user defines a + // GeneratedExtension manually and gives it a different type. + // This should not happen in normal use. But, to be nice, we'll + // copy the message to whatever type the caller was expecting. + return MessageDefaultInstance.WeakCreateBuilderForType() + .WeakMergeFrom((IMessage)value).WeakBuild(); + } + case MappedType.Enum: + // Just return a boxed int - that can be unboxed to the enum + EnumValueDescriptor enumValue = (EnumValueDescriptor) value; + return enumValue.Number; + default: + return value; + } + } + + /// <summary> + /// Converts from the type used by the native accessors to the type + /// used by reflection accessors. For example, the reflection accessors + /// for enums use EnumValueDescriptors but the native accessors use + /// the generated enum type. + /// </summary> + public object ToReflectionType(object value) { + if (descriptor.IsRepeated) { + if (descriptor.MappedType == MappedType.Enum) { + // Must convert the whole list. + IList<object> result = new List<object>(); + foreach (object element in (IEnumerable) value) { + result.Add(SingularToReflectionType(element)); + } + return result; + } else { + return value; + } + } else { + return SingularToReflectionType(value); + } + } + + /// <summary> + /// Like ToReflectionType(object) but for a single element. + /// </summary> + internal Object SingularToReflectionType(object value) { + return descriptor.MappedType == MappedType.Enum + ? descriptor.EnumType.FindValueByNumber((int) value) + : value; + } + + public abstract object FromReflectionType(object value); + } +}
\ No newline at end of file diff --git a/src/ProtocolBuffers/GeneratedMessage.cs b/src/ProtocolBuffers/GeneratedMessage.cs new file mode 100644 index 00000000..7801d521 --- /dev/null +++ b/src/ProtocolBuffers/GeneratedMessage.cs @@ -0,0 +1,139 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.Descriptors; +using Google.ProtocolBuffers.FieldAccess; +using System.Collections; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// All generated protocol message classes extend this class. It implements + /// most of the IMessage interface using reflection. Users + /// can ignore this class as an implementation detail. + /// </summary> + public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage<TMessage, TBuilder> + where TMessage : GeneratedMessage<TMessage, TBuilder> + where TBuilder : GeneratedBuilder<TMessage, TBuilder> { + + private UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance; + + /// <summary> + /// Returns the message as a TMessage. + /// </summary> + protected abstract TMessage ThisMessage { get; } + + internal FieldAccessorTable<TMessage, TBuilder> FieldAccessorsFromBuilder { + get { return InternalFieldAccessors; } + } + + protected abstract FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { get; } + + public override MessageDescriptor DescriptorForType { + get { return InternalFieldAccessors.Descriptor; } + } + + internal IDictionary<FieldDescriptor, Object> GetMutableFieldMap() { + + // Use a SortedList so we'll end up serializing fields in order + var ret = new SortedList<FieldDescriptor, object>(); + MessageDescriptor descriptor = DescriptorForType; + foreach (FieldDescriptor field in descriptor.Fields) { + IFieldAccessor<TMessage, TBuilder> accessor = InternalFieldAccessors[field]; + if (field.IsRepeated) { + if (accessor.GetRepeatedCount(ThisMessage) != 0) { + ret[field] = accessor.GetValue(ThisMessage); + } + } else if (HasField(field)) { + ret[field] = accessor.GetValue(ThisMessage); + } + } + return ret; + } + + public override bool IsInitialized { + get { + /* if (!DescriptorForType.HasRequiredFields) { + return true; + }*/ + // Check that all required fields are present. + foreach (FieldDescriptor field in DescriptorForType.Fields) { + if (field.IsRequired && !HasField(field)) { + return false; + } + } + + // Check that embedded messages are initialized. + // This code is similar to that in AbstractMessage, but we don't + // fetch all the field values - just the ones we need to. + foreach (FieldDescriptor field in DescriptorForType.Fields) { + if (field.MappedType == MappedType.Message) { + if (field.IsRepeated) { + // We know it's an IList<T>, but not the exact type - so + // IEnumerable is the best we can do. (C# generics aren't covariant yet.) + foreach (IMessage element in (IEnumerable) this[field]) { + if (!element.IsInitialized) { + return false; + } + } + } else { + if (HasField(field) && !((IMessage) this[field]).IsInitialized) { + return false; + } + } + } + } + return true; + } + } + + public override IDictionary<FieldDescriptor, object> AllFields { + get { return Dictionaries.AsReadOnly(GetMutableFieldMap()); } + } + + public override bool HasField(FieldDescriptor field) { + return InternalFieldAccessors[field].Has(ThisMessage); + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + return InternalFieldAccessors[field].GetRepeatedCount(ThisMessage); + } + + public override object this[FieldDescriptor field, int index] { + get { return InternalFieldAccessors[field].GetRepeatedValue(ThisMessage, index); } + } + + public override object this[FieldDescriptor field] { + get { return InternalFieldAccessors[field].GetValue(ThisMessage); } + } + + public override UnknownFieldSet UnknownFields { + get { return unknownFields; } + } + + /// <summary> + /// Replaces the set of unknown fields for this message. This should + /// only be used before a message is built, by the builder. (In the + /// Java code it is private, but the builder is nested so has access + /// to it.) + /// </summary> + internal void SetUnknownFields(UnknownFieldSet fieldSet) { + unknownFields = fieldSet; + } + } +} diff --git a/src/ProtocolBuffers/GeneratedRepeatExtension.cs b/src/ProtocolBuffers/GeneratedRepeatExtension.cs new file mode 100644 index 00000000..ae711bd2 --- /dev/null +++ b/src/ProtocolBuffers/GeneratedRepeatExtension.cs @@ -0,0 +1,57 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using Google.ProtocolBuffers.Descriptors; +using System.Collections; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Class used to represent repeat extensions in generated classes. + /// </summary> + public sealed class GeneratedRepeatExtension<TExtensionElement> : GeneratedExtensionBase<IList<TExtensionElement>> { + private GeneratedRepeatExtension(FieldDescriptor field) : base(field, typeof(TExtensionElement)) { + } + + public static GeneratedExtensionBase<IList<TExtensionElement>> CreateInstance(FieldDescriptor descriptor) { + if (!descriptor.IsRepeated) { + throw new ArgumentException("Must call GeneratedRepeatExtension.CreateInstance() for repeated types."); + } + return new GeneratedRepeatExtension<TExtensionElement>(descriptor); + } + + /// <summary> + /// Converts the list to the right type. + /// TODO(jonskeet): Check where this is used, and whether we need to convert + /// for primitive types. + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + public override object FromReflectionType(object value) { + if (Descriptor.MappedType == MappedType.Message || + Descriptor.MappedType == MappedType.Enum) { + // Must convert the whole list. + List<TExtensionElement> result = new List<TExtensionElement>(); + foreach (object element in (IEnumerable) value) { + result.Add((TExtensionElement) SingularFromReflectionType(element)); + } + return result; + } else { + return value; + } + } + } +} diff --git a/src/ProtocolBuffers/GeneratedSingleExtension.cs b/src/ProtocolBuffers/GeneratedSingleExtension.cs new file mode 100644 index 00000000..55450f21 --- /dev/null +++ b/src/ProtocolBuffers/GeneratedSingleExtension.cs @@ -0,0 +1,39 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// Generated extension for a singular field. + /// </remarks> + public sealed class GeneratedSingleExtension<TExtension> : GeneratedExtensionBase<TExtension> { + internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor, typeof(TExtension)) { + } + + public static GeneratedSingleExtension<TExtension> CreateInstance(FieldDescriptor descriptor) { + if (descriptor.IsRepeated) { + throw new ArgumentException("Must call GeneratedRepeateExtension.CreateInstance() for repeated types."); + } + return new GeneratedSingleExtension<TExtension>(descriptor); + } + + public override object FromReflectionType(object value) { + return base.SingularFromReflectionType(value); + } + } +} diff --git a/src/ProtocolBuffers/IBuilder.cs b/src/ProtocolBuffers/IBuilder.cs new file mode 100644 index 00000000..4100dedd --- /dev/null +++ b/src/ProtocolBuffers/IBuilder.cs @@ -0,0 +1,283 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using System.IO; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// Non-generic interface for all members whose signatures don't require knowledge of + /// the type being built. The generic interface extends this one. Some methods return + /// either an IBuilder or an IMessage; in these cases the generic interface redeclares + /// the same method with a type-specific signature. Implementations are encouraged to + /// use explicit interface implemenation for the non-generic form. This mirrors + /// how IEnumerable and IEnumerable<T> work. + /// </summary> + public interface IBuilder { + /// <summary> + /// Returns true iff all required fields in the message and all + /// embedded messages are set. + /// </summary> + bool IsInitialized { get; } + + /// <summary> + /// Only present in the nongeneric interface - useful for tests, but + /// not as much in real life. + /// </summary> + IBuilder SetField(FieldDescriptor field, object value); + + /// <summary> + /// Only present in the nongeneric interface - useful for tests, but + /// not as much in real life. + /// </summary> + IBuilder SetRepeatedField(FieldDescriptor field, int index, object value); + + /// <summary> + /// Behaves like the equivalent property in IMessage<T>. + /// The returned map may or may not reflect future changes to the builder. + /// Either way, the returned map is unmodifiable. + /// </summary> + IDictionary<FieldDescriptor, object> AllFields { get; } + + /// <summary> + /// Allows getting and setting of a field. + /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor)"/> + /// </summary> + /// <param name="field"></param> + /// <returns></returns> + object this[FieldDescriptor field] { get; set; } + + /// <summary> + /// Get the message's type descriptor. + /// <see cref="IMessage{TMessage, TBuilder}.DescriptorForType"/> + /// </summary> + MessageDescriptor DescriptorForType { get; } + + /// <summary> + /// <see cref="IMessage{TMessage, TBuilder}.GetRepeatedFieldCount"/> + /// </summary> + /// <param name="field"></param> + /// <returns></returns> + int GetRepeatedFieldCount(FieldDescriptor field); + + /// <summary> + /// Allows getting and setting of a repeated field value. + /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor, int)"/> + /// </summary> + object this[FieldDescriptor field, int index] { get; set; } + + /// <summary> + /// <see cref="IMessage{TMessage, TBuilder}.HasField"/> + /// </summary> + bool HasField(FieldDescriptor field); + + /// <summary> + /// <see cref="IMessage{TMessage, TBuilder}.UnknownFields"/> + /// </summary> + UnknownFieldSet UnknownFields { get; set; } + + /// <summary> + /// Create a builder for messages of the appropriate type for the given field. + /// Messages built with this can then be passed to the various mutation properties + /// and methods. + /// </summary> + IBuilder CreateBuilderForField(FieldDescriptor field); + + #region Methods which are like those of the generic form, but without any knowledge of the type parameters + IBuilder WeakAddRepeatedField(FieldDescriptor field, object value); + IBuilder WeakClear(); + IBuilder WeakClearField(FieldDescriptor field); + IBuilder WeakMergeFrom(IMessage message); + IBuilder WeakMergeFrom(ByteString data); + IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry); + IBuilder WeakMergeFrom(CodedInputStream input); + IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry); + IMessage WeakBuild(); + IMessage WeakBuildPartial(); + IBuilder WeakClone(); + IMessage WeakDefaultInstanceForType { get; } + #endregion + } + + /// <summary> + /// Interface implemented by Protocol Message builders. + /// TODO(jonskeet): Consider "SetXXX" methods returning the builder, as well as the properties. + /// </summary> + /// <typeparam name="TMessage">Type of message</typeparam> + /// <typeparam name="TBuilder">Type of builder</typeparam> + public interface IBuilder<TMessage, TBuilder> : IBuilder + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + + TBuilder SetUnknownFields(UnknownFieldSet unknownFields); + + /// <summary> + /// Resets all fields to their default values. + /// </summary> + TBuilder Clear(); + + /// <summary> + /// Merge the specified other message into the message being + /// built. Merging occurs as follows. For each field: + /// For singular primitive fields, if the field is set in <paramref name="other"/>, + /// then <paramref name="other"/>'s value overwrites the value in this message. + /// For singular message fields, if the field is set in <paramref name="other"/>, + /// it is merged into the corresponding sub-message of this message using the same + /// merging rules. + /// For repeated fields, the elements in <paramref name="other"/> are concatenated + /// with the elements in this message. + /// </summary> + /// <param name="other"></param> + /// <returns></returns> + TBuilder MergeFrom(TMessage other); + + /// <summary> + /// Merge the specified other message which may be a different implementation of + /// the same message descriptor. + /// </summary> + TBuilder MergeFrom(IMessage other); + + /// <summary> + /// Constructs the final message. Once this is called, this Builder instance + /// is no longer valid, and calling any other method may throw a + /// NullReferenceException. If you need to continue working with the builder + /// after calling Build, call Clone first. + /// </summary> + /// <exception cref="UninitializedMessageException">the message + /// is missing one or more required fields; use BuildPartial to bypass + /// this check</exception> + TMessage Build(); + + /// <summary> + /// Like Build(), but does not throw an exception if the message is missing + /// required fields. Instead, a partial message is returned. + /// </summary> + TMessage BuildPartial(); + + /// <summary> + /// Clones this builder. + /// TODO(jonskeet): Explain depth of clone. + /// </summary> + TBuilder Clone(); + + /// <summary> + /// Parses a message of this type from the input and merges it with this + /// message, as if using MergeFrom(IMessage<T>). + /// </summary> + /// <remarks> + /// Warning: This does not verify that all required fields are present + /// in the input message. If you call Build() without setting all + /// required fields, it will throw an UninitializedMessageException. + /// There are a few good ways to deal with this: + /// <list> + /// <item>Call IsInitialized to verify to verify that all required fields are + /// set before building.</item> + /// <item>Parse the message separately using one of the static ParseFrom + /// methods, then use MergeFrom(IMessage<T>) to merge it with + /// this one. ParseFrom will throw an InvalidProtocolBufferException + /// (an IOException) if some required fields are missing. + /// Use BuildPartial to build, which ignores missing required fields. + /// </list> + /// </remarks> + TBuilder MergeFrom(CodedInputStream input); + + /// <summary> + /// Like MergeFrom(CodedInputStream), but also parses extensions. + /// The extensions that you want to be able to parse must be registered + /// in <paramref name="extensionRegistry"/>. Extensions not in the registry + /// will be treated as unknown fields. + /// </summary> + TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry); + + /// <summary> + /// Get's the message's type's default instance. + /// <see cref="IMessage{TMessage}.DefaultInstanceForType" /> + /// </summary> + TMessage DefaultInstanceForType { get; } + + /// <summary> + /// Clears the field. This is exactly equivalent to calling the generated + /// Clear method corresponding to the field. + /// </summary> + /// <param name="field"></param> + /// <returns></returns> + TBuilder ClearField(FieldDescriptor field); + + /// <summary> + /// Appends the given value as a new element for the specified repeated field. + /// </summary> + /// <exception cref="ArgumentException">the field is not a repeated field, + /// the field does not belong to this builder's type, or the value is + /// of the incorrect type + /// </exception> + TBuilder AddRepeatedField(FieldDescriptor field, object value); + + /// <summary> + /// Merge some unknown fields into the set for this message. + /// </summary> + TBuilder MergeUnknownFields(UnknownFieldSet unknownFields); + + #region Convenience methods + /// <summary> + /// Parse <paramref name="data"/> as a message of this type and merge + /// it with the message being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream). + /// </summary> + TBuilder MergeFrom(ByteString data); + + /// <summary> + /// Parse <paramref name="data"/> as a message of this type and merge + /// it with the message being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream, ExtensionRegistry). + /// </summary> + TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry); + + /// <summary> + /// Parse <paramref name="data"/> as a message of this type and merge + /// it with the message being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream). + /// </summary> + TBuilder MergeFrom(byte[] data); + + /// <summary> + /// Parse <paramref name="data"/> as a message of this type and merge + /// it with the message being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream, ExtensionRegistry). + /// </summary> + TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry); + + /// <summary> + /// Parse <paramref name="input"/> as a message of this type and merge + /// it with the message being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream). Note that this method always reads + /// the entire input (unless it throws an exception). If you want it to + /// stop earlier, you will need to wrap the input in a wrapper + /// stream which limits reading. Despite usually reading the entire + /// stream, this method never closes the stream. + /// </summary> + TBuilder MergeFrom(Stream input); + + /// <summary> + /// Parse <paramref name="input"/> as a message of this type and merge + /// it with the message being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream, ExtensionRegistry). + /// </summary> + TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry); + #endregion + } +} diff --git a/src/ProtocolBuffers/IMessage.cs b/src/ProtocolBuffers/IMessage.cs new file mode 100644 index 00000000..1ce18a5c --- /dev/null +++ b/src/ProtocolBuffers/IMessage.cs @@ -0,0 +1,186 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using System.IO; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// Non-generic interface used for all parts of the API which don't require + /// any type knowledge. + /// </summary> + public interface IMessage { + /// <summary> + /// Returns the message's type's descriptor. This differs from the + /// Descriptor property of each generated message class in that this + /// method is an abstract method of IMessage whereas Descriptor is + /// a static property of a specific class. They return the same thing. + /// </summary> + MessageDescriptor DescriptorForType { get; } + /// <summary> + /// Returns a collection of all the fields in this message which are set + /// and their corresponding values. A singular ("required" or "optional") + /// field is set iff HasField() returns true for that field. A "repeated" + /// field is set iff GetRepeatedFieldSize() is greater than zero. The + /// values are exactly what would be returned by calling + /// GetField(FieldDescriptor) for each field. The map + /// is guaranteed to be a sorted map, so iterating over it will return fields + /// in order by field number. + /// </summary> + IDictionary<FieldDescriptor, object> AllFields { get; } + + /// <summary> + /// Returns true if the given field is set. This is exactly equivalent + /// to calling the generated "Has" property corresponding to the field. + /// </summary> + /// <exception cref="ArgumentException">the field is a repeated field, + /// or it's not a field of this type</exception> + bool HasField(FieldDescriptor field); + + /// <summary> + /// Obtains the value of the given field, or the default value if + /// it isn't set. For value type fields, the boxed value is returned. + /// For enum fields, the EnumValueDescriptor for the enum is returned. + /// For embedded message fields, the sub-message + /// is returned. For repeated fields, an IList<T> is returned. + /// </summary> + object this[FieldDescriptor field] { get; } + + /// <summary> + /// Returns the number of elements of a repeated field. This is + /// exactly equivalent to calling the generated "Count" property + /// corresponding to the field. + /// </summary> + /// <exception cref="ArgumentException">the field is not a repeated field, + /// or it's not a field of this type</exception> + int GetRepeatedFieldCount(FieldDescriptor field); + + /// <summary> + /// Gets an element of a repeated field. For value type fields + /// including enums, the boxed value is returned. For embedded + /// message fields, the sub-message is returned. + /// </summary> + /// <exception cref="ArgumentException">the field is not a repeated field, + /// or it's not a field of this type</exception> + /// <exception cref="ArgumentOutOfRangeException">the index is out of + /// range for the repeated field's value</exception> + object this[FieldDescriptor field, int index] { get; } + + /// <summary> + /// Returns the unknown fields for this message. + /// </summary> + UnknownFieldSet UnknownFields { get; } + + /// <summary> + /// Returns true iff all required fields in the message and all embedded + /// messages are set. + /// </summary> + bool IsInitialized { get; } + + /// <summary> + /// Serializes the message and writes it to the given output stream. + /// This does not flush or close the stream. + /// </summary> + /// <param name="output"></param> + void WriteTo(CodedOutputStream output); + + /// <summary> + /// Returns the number of bytes required to encode this message. + /// The result is only computed on the first call and memoized after that. + /// </summary> + int SerializedSize { get; } + + #region Comparison and hashing + /// <summary> + /// Compares the specified object with this message for equality. + /// Returns true iff the given object is a message of the same type + /// (as defined by DescriptorForType) and has identical values + /// for all its fields. + /// </summary> + bool Equals(object other); + + /// <summary> + /// Returns the hash code value for this message. + /// TODO(jonskeet): Specify the hash algorithm, but better than the Java one! + /// </summary> + int GetHashCode(); + #endregion + + #region Convenience methods + /// <summary> + /// Converts the message to a string in protocol buffer text format. + /// This is just a trivial wrapper around TextFormat.PrintToString. + /// </summary> + string ToString(); + + /// <summary> + /// Serializes the message to a ByteString. This is a trivial wrapper + /// around WriteTo(CodedOutputStream). + /// </summary> + ByteString ToByteString(); + + /// <summary> + /// Serializes the message to a byte array. This is a trivial wrapper + /// around WriteTo(CodedOutputStream). + /// </summary> + byte[] ToByteArray(); + + /// <summary> + /// Serializes the message and writes it to the given stream. + /// This is just a wrapper around WriteTo(CodedOutputStream). This + /// does not flush or close the stream. + /// </summary> + /// <param name="output"></param> + void WriteTo(Stream output); + #endregion + + /// <summary> + /// Creates a builder for the type, but in a weakly typed manner. This + /// is typically implemented by strongly typed builders by just returning + /// the result of CreateBuilderForType. + /// </summary> + IBuilder WeakCreateBuilderForType(); + + IMessage WeakDefaultInstanceForType { get; } + } + + public interface IMessage<TMessage> : IMessage { + /// <summary> + /// Returns an instance of this message type with all fields set to + /// their default values. This may or may not be a singleton. This differs + /// from the DefaultInstance property of each generated message class in that this + /// method is an abstract method of IMessage whereas DefaultInstance is + /// a static property of a specific class. They return the same thing. + /// </summary> + TMessage DefaultInstanceForType { get; } + } + + /// <summary> + /// Type-safe interface for all generated messages to implement. + /// </summary> + public interface IMessage<TMessage, TBuilder> : IMessage<TMessage> + where TMessage : IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + #region Builders + /// <summary> + /// Constructs a new builder for a message of the same type as this message. + /// </summary> + TBuilder CreateBuilderForType(); + #endregion + } +} diff --git a/src/ProtocolBuffers/IRpcChannel.cs b/src/ProtocolBuffers/IRpcChannel.cs new file mode 100644 index 00000000..59427835 --- /dev/null +++ b/src/ProtocolBuffers/IRpcChannel.cs @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Interface for an RPC channel. A channel represents a communication line to + /// a service (IService implementation) which can be used to call that service's + /// methods. The service may be running on another machine. Normally, you should + /// not call an IRpcChannel directly, but instead construct a stub wrapping it. + /// Generated service classes contain a CreateStub method for precisely this purpose. + /// </summary> + public interface IRpcChannel { + /// <summary> + /// Calls the given method of the remote service. This method is similar + /// to <see cref="IService.CallMethod" /> with one important difference: the + /// caller decides the types of the IMessage objects, not the implementation. + /// The request may be of any type as long as <c>request.Descriptor == method.InputType</c>. + /// The response passed to the callback will be of the same type as + /// <paramref name="responsePrototype"/> (which must be such that + /// <c>responsePrototype.Descriptor == method.OutputType</c>). + /// </summary> + void CallMethod(MethodDescriptor method, IRpcController controller, + IMessage request, IMessage responsePrototype, Action<IMessage> done); + } +} diff --git a/src/ProtocolBuffers/IRpcController.cs b/src/ProtocolBuffers/IRpcController.cs new file mode 100644 index 00000000..88cef2db --- /dev/null +++ b/src/ProtocolBuffers/IRpcController.cs @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Mediates a single method call. The primary purpose of the controller + /// is to provide a way to manipulate settings specific to the + /// RPC implementation and to find out about RPC-level errors. + /// + /// The methods provided by this interface are intended to be a "least + /// common denominator" set of features which we expect all implementations to + /// support. Specific implementations may provide more advanced features, + /// (e.g. deadline propagation). + /// </summary> + public interface IRpcController { + + #region Client side calls + // These calls may be made from the client side only. Their results + // are undefined on the server side (may throw exceptions). + + /// <summary> + /// Resets the controller to its initial state so that it may be reused in + /// a new call. This can be called from the client side only. It must not + /// be called while an RPC is in progress. + /// </summary> + void Reset(); + + /// <summary> + /// After a call has finished, returns true if the call failed. The possible + /// reasons for failure depend on the RPC implementation. Failed must + /// only be called on the client side, and must not be called before a call has + /// finished. + /// </summary> + bool Failed { get; } + + /// <summary> + /// If Failed is true, ErrorText returns a human-readable description of the error. + /// </summary> + string ErrorText { get; } + + /// <summary> + /// Advises the RPC system that the caller desires that the RPC call be + /// canceled. The RPC system may cancel it immediately, may wait awhile and + /// then cancel it, or may not even cancel the call at all. If the call is + /// canceled, the "done" callback will still be called and the RpcController + /// will indicate that the call failed at that time. + /// </summary> + void StartCancel(); + #endregion + + #region Server side calls + // These calls may be made from the server side only. Their results + // are undefined on the client side (may throw exceptions). + + /// <summary> + /// Causes Failed to return true on the client side. <paramref name="reason"/> + /// will be incorporated into the message returned by ErrorText. + /// If you find you need to return machine-readable information about + /// failures, you should incorporate it into your response protocol buffer + /// and should *not* call SetFailed. + /// </summary> + void SetFailed(string reason); + + /// <summary> + /// If true, indicates that the client canceled the RPC, so the server may as + /// well give up on replying to it. This method must be called on the server + /// side only. The server should still call the final "done" callback. + /// </summary> + bool isCanceled(); + + /// <summary> + /// Requests that the given callback be called when the RPC is canceled. + /// The parameter passed to the callback will always be null. The callback will + /// be called exactly once. If the RPC completes without being canceled, the + /// callback will be called after completion. If the RPC has already been canceled + /// when NotifyOnCancel is called, the callback will be called immediately. + /// + /// NotifyOnCancel must be called no more than once per request. It must be + /// called on the server side only. + /// </summary> + /// <param name="callback"></param> + void NotifyOnCancel(Action<object> callback); + #endregion + } +} diff --git a/src/ProtocolBuffers/IService.cs b/src/ProtocolBuffers/IService.cs new file mode 100644 index 00000000..4bf1e352 --- /dev/null +++ b/src/ProtocolBuffers/IService.cs @@ -0,0 +1,79 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Base interface for protocol-buffer-based RPC services. Services themselves + /// are abstract classes (implemented either by servers or as stubs) but they + /// implement this itnerface. The methods of this interface can be used to call + /// the methods of the service without knowing its exact type at compile time + /// (analagous to the IMessage interface). + /// </summary> + public interface IService { + /// <summary> + /// The ServiceDescriptor describing this service and its methods. + /// </summary> + ServiceDescriptor DescriptorForType { get; } + + /// <summary> + /// Call a method of the service specified by MethodDescriptor. This is + /// normally implemented as a simple switch that calls the standard + /// definitions of the service's methods. + /// <para> + /// Preconditions + /// <list> + /// <item><c>method.Service == DescriptorForType</c></item> + /// <item>request is of the exact same class as the object returned by GetRequestPrototype(method)</item> + /// <item>controller is of the correct type for the RPC implementation being used by this service. + /// For stubs, the "correct type" depends on the IRpcChannel which the stub is using. Server-side + /// implementations are expected to accept whatever type of IRpcController the server-side RPC implementation + /// uses.</item> + /// </list> + /// </para> + /// <para> + /// Postconditions + /// <list> + /// <item><paramref name="done" /> will be called when the method is complete. + /// This may before CallMethod returns or it may be at some point in the future.</item> + /// <item>The parameter to <paramref name="done"/> is the response. It will be of the + /// exact same type as would be returned by <see cref="GetResponsePrototype"/>.</item> + /// <item>If the RPC failed, the parameter to <paramref name="done"/> will be null. + /// Further details about the failure can be found by querying <paramref name="controller"/>.</item> + /// </list> + /// </para> + /// </summary> + void CallMethod(MethodDescriptor method, IRpcController controller, + IMessage request, Action<IMessage> done); + + /// <summary> + /// CallMethod requires that the request passed in is of a particular implementation + /// of IMessage. This method gets the default instance of this type of a given method. + /// You can then call WeakCreateBuilderForType to create a builder to build an object which + /// you can then pass to CallMethod. + /// </summary> + IMessage GetRequestPrototype(MethodDescriptor method); + + /// <summary> + /// Like GetRequestPrototype, but returns a prototype of the response message. + /// This is generally not needed because the IService implementation contructs + /// the response message itself, but it may be useful in some cases to know ahead + /// of time what type of object will be returned. + /// </summary> + IMessage GetResponsePrototype(MethodDescriptor method); + } +} diff --git a/src/ProtocolBuffers/InvalidProtocolBufferException.cs b/src/ProtocolBuffers/InvalidProtocolBufferException.cs new file mode 100644 index 00000000..4f1b1a92 --- /dev/null +++ b/src/ProtocolBuffers/InvalidProtocolBufferException.cs @@ -0,0 +1,80 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.IO; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Thrown when a protocol message being parsed is invalid in some way, + /// e.g. it contains a malformed varint or a negative byte length. + /// </summary> + public sealed class InvalidProtocolBufferException : IOException { + + internal InvalidProtocolBufferException(string message) + : base(message) { + } + + internal static InvalidProtocolBufferException TruncatedMessage() { + return new InvalidProtocolBufferException( + "While parsing a protocol message, the input ended unexpectedly " + + "in the middle of a field. This could mean either than the " + + "input has been truncated or that an embedded message " + + "misreported its own length."); + } + + internal static InvalidProtocolBufferException NegativeSize() { + return new InvalidProtocolBufferException( + "CodedInputStream encountered an embedded string or message " + + "which claimed to have negative size."); + } + + public static InvalidProtocolBufferException MalformedVarint() { + return new InvalidProtocolBufferException( + "CodedInputStream encountered a malformed varint."); + } + + internal static InvalidProtocolBufferException InvalidTag() { + return new InvalidProtocolBufferException( + "Protocol message contained an invalid tag (zero)."); + } + + internal static InvalidProtocolBufferException InvalidEndTag() { + return new InvalidProtocolBufferException( + "Protocol message end-group tag did not match expected tag."); + } + + internal static InvalidProtocolBufferException InvalidWireType() { + return new InvalidProtocolBufferException( + "Protocol message tag had invalid wire type."); + } + + internal static InvalidProtocolBufferException RecursionLimitExceeded() { + return new InvalidProtocolBufferException( + "Protocol message had too many levels of nesting. May be malicious. " + + "Use CodedInputStream.SetRecursionLimit() to increase the depth limit."); + } + + internal static InvalidProtocolBufferException SizeLimitExceeded() { + return new InvalidProtocolBufferException( + "Protocol message was too large. May be malicious. " + + "Use CodedInputStream.SetSizeLimit() to increase the size limit."); + } + + internal static InvalidProtocolBufferException InvalidMessageStreamTag() { + return new InvalidProtocolBufferException( + "Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1."); + } + } +} diff --git a/src/ProtocolBuffers/MessageStreamIterator.cs b/src/ProtocolBuffers/MessageStreamIterator.cs new file mode 100644 index 00000000..61dbf840 --- /dev/null +++ b/src/ProtocolBuffers/MessageStreamIterator.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections; +using System.IO; +using System.Reflection; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// Iterates over data created using a <see cref="MessageStreamWriter{T}" />. + /// Unlike MessageStreamWriter, this class is not usually constructed directly with + /// a stream; instead it is provided with a way of opening a stream when iteration + /// is started. The stream is closed when the iteration is completed or the enumerator + /// is disposed. (This occurs naturally when using <c>foreach</c>.) + /// </summary> + public class MessageStreamIterator<TMessage> : IEnumerable<TMessage> + where TMessage : IMessage<TMessage> { + + private readonly StreamProvider streamProvider; + private readonly ExtensionRegistry extensionRegistry; + + /// <summary> + /// Delegate created via reflection trickery (once per type) to create a builder + /// and read a message from a CodedInputStream with it. Note that unlike in Java, + /// there's one static field per constructed type. + /// </summary> + private static readonly Func<CodedInputStream, ExtensionRegistry, TMessage> messageReader = BuildMessageReader(); + + /// <summary> + /// Any exception (within reason) thrown within messageReader is caught and rethrown in the constructor. + /// This makes life a lot simpler for the caller. + /// </summary> + private static Exception typeInitializationException; + + /// <summary> + /// Creates the delegate later used to read messages. This is only called once per type, but to + /// avoid exceptions occurring at confusing times, if this fails it will set typeInitializationException + /// to the appropriate error and return null. + /// </summary> + private static Func<CodedInputStream, ExtensionRegistry, TMessage> BuildMessageReader() { + try { + Type builderType = FindBuilderType(); + + // Yes, it's redundant to find this again, but it's only the once... + MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", Type.EmptyTypes); + Delegate builderBuilder = Delegate.CreateDelegate( + typeof(Func<>).MakeGenericType(builderType), null, createBuilderMethod); + + MethodInfo buildMethod = typeof(MessageStreamIterator<TMessage>) + .GetMethod("BuildImpl", BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod(typeof(TMessage), builderType); + + return (Func<CodedInputStream, ExtensionRegistry, TMessage>)Delegate.CreateDelegate( + typeof(Func<CodedInputStream, ExtensionRegistry, TMessage>), builderBuilder, buildMethod); + } catch (ArgumentException e) { + typeInitializationException = e; + } catch (InvalidOperationException e) { + typeInitializationException = e; + } catch (InvalidCastException e) { + // Can't see why this would happen, but best to know about it. + typeInitializationException = e; + } + return null; + } + + /// <summary> + /// Works out the builder type for TMessage, or throws an ArgumentException to explain why it can't. + /// This will check + /// </summary> + private static Type FindBuilderType() { + MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", Type.EmptyTypes); + if (createBuilderMethod == null) { + throw new ArgumentException("Message type " + typeof(TMessage).FullName + " has no CreateBuilder method."); + } + if (createBuilderMethod.ReturnType == typeof(void)) { + throw new ArgumentException("CreateBuilder method in " + typeof(TMessage).FullName + " has void return type"); + } + Type builderType = createBuilderMethod.ReturnType; + Type messageInterface = typeof(IMessage<,>).MakeGenericType(typeof(TMessage), builderType); + Type builderInterface = typeof(IBuilder<,>).MakeGenericType(typeof(TMessage), builderType); + if (Array.IndexOf(typeof(TMessage).GetInterfaces(), messageInterface) == -1) { + throw new ArgumentException("Message type " + typeof(TMessage) + " doesn't implement " + messageInterface.FullName); + } + if (Array.IndexOf(builderType.GetInterfaces(), builderInterface) == -1) { + throw new ArgumentException("Builder type " + typeof(TMessage) + " doesn't implement " + builderInterface.FullName); + } + return builderType; + } + + /// <summary> + /// Method we'll use to build messageReader, with the first parameter fixed to TMessage.CreateBuilder. Note that we + /// have to introduce another type parameter (TMessage2) as we can't constrain TMessage for just a single method + /// (and we can't do it at the type level because we don't know TBuilder). However, by constraining TMessage2 + /// to not only implement IMessage appropriately but also to derive from TMessage2, we can avoid doing a cast + /// for every message; the implicit reference conversion will be fine. In practice, TMessage2 and TMessage will + /// be the same type when we construct the generic method by reflection. + /// </summary> + private static TMessage BuildImpl<TMessage2, TBuilder>(Func<TBuilder> builderBuilder, CodedInputStream input, ExtensionRegistry registry) + where TBuilder : IBuilder<TMessage2, TBuilder> + where TMessage2 : TMessage, IMessage<TMessage2, TBuilder> { + TBuilder builder = builderBuilder(); + input.ReadMessage(builder, registry); + return builder.Build(); + } + + private static readonly uint ExpectedTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + + private MessageStreamIterator(StreamProvider streamProvider, ExtensionRegistry extensionRegistry) { + if (messageReader == null) { + throw typeInitializationException; + } + this.streamProvider = streamProvider; + this.extensionRegistry = extensionRegistry; + } + + /// <summary> + /// Creates a new instance which uses the same stream provider as this one, + /// but the specified extension registry. + /// </summary> + public MessageStreamIterator<TMessage> WithExtensionRegistry(ExtensionRegistry newRegistry) { + return new MessageStreamIterator<TMessage>(streamProvider, newRegistry); + } + + public static MessageStreamIterator<TMessage> FromFile(string file) { + return new MessageStreamIterator<TMessage>(() => File.OpenRead(file), ExtensionRegistry.Empty); + } + + public static MessageStreamIterator<TMessage> FromStreamProvider(StreamProvider streamProvider) { + return new MessageStreamIterator<TMessage>(streamProvider, ExtensionRegistry.Empty); + } + + public IEnumerator<TMessage> GetEnumerator() { + using (Stream stream = streamProvider()) { + CodedInputStream input = CodedInputStream.CreateInstance(stream); + uint tag; + while ((tag = input.ReadTag()) != 0) { + if (tag != ExpectedTag) { + throw InvalidProtocolBufferException.InvalidMessageStreamTag(); + } + yield return messageReader(input, extensionRegistry); + } + } + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + } +} diff --git a/src/ProtocolBuffers/MessageStreamWriter.cs b/src/ProtocolBuffers/MessageStreamWriter.cs new file mode 100644 index 00000000..9ff33b05 --- /dev/null +++ b/src/ProtocolBuffers/MessageStreamWriter.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Writes multiple messages to the same stream. Each message is written + /// as if it were an element of a repeated field 1 in a larger protocol buffer. + /// This class takes no ownership of the stream it is given; it never closes the + /// stream. + /// </summary> + public sealed class MessageStreamWriter<T> where T : IMessage<T> { + + private readonly CodedOutputStream codedOutput; + + /// <summary> + /// Creates an instance which writes to the given stream. + /// </summary> + /// <param name="output">Stream to write messages to.</param> + public MessageStreamWriter(Stream output) { + codedOutput = CodedOutputStream.CreateInstance(output); + } + + public void Write(T message) { + codedOutput.WriteMessage(1, message); + } + + public void Flush() { + codedOutput.Flush(); + } + } +} diff --git a/src/ProtocolBuffers/Properties/AssemblyInfo.cs b/src/ProtocolBuffers/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..749a2e45 --- /dev/null +++ b/src/ProtocolBuffers/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ProtocolBuffers")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ProtocolBuffers")] +[assembly: AssemblyCopyright("Copyright © 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("279b643d-70e8-47ae-9eb1-500d1c48bab6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly:InternalsVisibleTo("Google.ProtocolBuffers.Test,PublicKey="+ +"00240000048000009400000006020000002400005253413100040000010001008179f2dd31a648"+ +"2a2359dbe33e53701167a888e7c369a9ae3210b64f93861d8a7d286447e58bc167e3d99483beda"+ +"72f738140072bb69990bc4f98a21365de2c105e848974a3d210e938b0a56103c0662901efd6b78"+ +"0ee6dbe977923d46a8fda18fb25c65dd73b149a5cd9f3100668b56649932dadd8cf5be52eb1dce"+ +"ad5cedbf")] +[assembly: InternalsVisibleTo("ProtoGen,PublicKey=" + +"00240000048000009400000006020000002400005253413100040000010001006d739020e13bdc" + +"038e86fa8aa5e1b13aae65d3ae79d622816c6067ab5b6955be50cc887130117582349208c13a55" + +"5e09a6084558f989ccde66094f07822808d3a9b922b0e85b912070032e90bb35360be7efb7982b" + +"702d7a5c6ed1e21d8ca587b4f4c9d2b81210d3641cc75f506cdfc628ac5453ff0a6886986c981d" + +"12245bc7")] diff --git a/src/ProtocolBuffers/Properties/Google.ProtocolBuffers.snk b/src/ProtocolBuffers/Properties/Google.ProtocolBuffers.snk Binary files differnew file mode 100644 index 00000000..6bbfc90f --- /dev/null +++ b/src/ProtocolBuffers/Properties/Google.ProtocolBuffers.snk diff --git a/src/ProtocolBuffers/ProtocolBuffers.csproj b/src/ProtocolBuffers/ProtocolBuffers.csproj new file mode 100644 index 00000000..3f76aa7f --- /dev/null +++ b/src/ProtocolBuffers/ProtocolBuffers.csproj @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Google.ProtocolBuffers</RootNamespace> + <AssemblyName>Google.ProtocolBuffers</AssemblyName> + <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <SignAssembly>true</SignAssembly> + <AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.snk</AssemblyOriginatorKeyFile> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="AbstractBuilder.cs" /> + <Compile Include="AbstractMessage.cs" /> + <Compile Include="ByteString.cs" /> + <Compile Include="Collections\PopsicleList.cs" /> + <Compile Include="Delegates.cs" /> + <Compile Include="CodedInputStream.cs" /> + <Compile Include="CodedOutputStream.cs" /> + <Compile Include="Collections\Dictionaries.cs" /> + <Compile Include="Collections\Lists.cs" /> + <Compile Include="Collections\ReadOnlyDictionary.cs" /> + <Compile Include="DescriptorProtos\CSharpOptions.cs" /> + <Compile Include="DescriptorProtos\DescriptorProtoFile.cs" /> + <Compile Include="DescriptorProtos\IDescriptorProto.cs" /> + <Compile Include="DescriptorProtos\PartialClasses.cs" /> + <Compile Include="Descriptors\DescriptorBase.cs" /> + <Compile Include="Descriptors\DescriptorPool.cs" /> + <Compile Include="Descriptors\DescriptorUtil.cs" /> + <Compile Include="Descriptors\DescriptorValidationException.cs" /> + <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\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" /> + <Compile Include="Descriptors\ServiceDescriptor.cs" /> + <Compile Include="DynamicMessage.cs" /> + <Compile Include="ExtendableBuilder.cs" /> + <Compile Include="ExtendableMessage.cs" /> + <Compile Include="ExtensionInfo.cs" /> + <Compile Include="ExtensionRegistry.cs" /> + <Compile Include="FieldAccess\ReflectionUtil.cs" /> + <Compile Include="FieldAccess\SingleEnumAccessor.cs" /> + <Compile Include="FieldAccess\SingleMessageAccessor.cs" /> + <Compile Include="FieldAccess\SinglePrimitiveAccessor.cs" /> + <Compile Include="FieldAccess\RepeatedPrimitiveAccessor.cs" /> + <Compile Include="FieldAccess\RepeatedEnumAccessor.cs" /> + <Compile Include="FieldAccess\IFieldAccessor.cs" /> + <Compile Include="FieldAccess\FieldAccessorTable.cs" /> + <Compile Include="FieldAccess\RepeatedMessageAccessor.cs" /> + <Compile Include="FieldSet.cs" /> + <Compile Include="GeneratedBuilder.cs" /> + <Compile Include="GeneratedRepeatExtension.cs" /> + <Compile Include="GeneratedSingleExtension.cs" /> + <Compile Include="GeneratedMessage.cs" /> + <Compile Include="IBuilder.cs" /> + <Compile Include="GeneratedExtensionBase.cs" /> + <Compile Include="IMessage.cs" /> + <Compile Include="InvalidProtocolBufferException.cs" /> + <Compile Include="IRpcChannel.cs" /> + <Compile Include="IRpcController.cs" /> + <Compile Include="IService.cs" /> + <Compile Include="MessageStreamIterator.cs" /> + <Compile Include="MessageStreamWriter.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="RpcUtil.cs" /> + <Compile Include="TextFormat.cs" /> + <Compile Include="TextGenerator.cs" /> + <Compile Include="TextTokenizer.cs" /> + <Compile Include="UninitializedMessageException.cs" /> + <Compile Include="UnknownField.cs" /> + <Compile Include="UnknownFieldSet.cs" /> + <Compile Include="WireFormat.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="Properties\Google.ProtocolBuffers.snk" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/src/ProtocolBuffers/RpcUtil.cs b/src/ProtocolBuffers/RpcUtil.cs new file mode 100644 index 00000000..bf383b45 --- /dev/null +++ b/src/ProtocolBuffers/RpcUtil.cs @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Grab-bag of utility functions useful when dealing with RPCs. + /// </summary> + public static class RpcUtil { + + /// <summary> + /// Converts an Action[IMessage] to an Action[T]. + /// </summary> + public static Action<T> SpecializeCallback<T>(Action<IMessage> action) + where T : IMessage<T> { + return message => action(message); + } + + /// <summary> + /// Converts an Action[T] to an Action[IMessage]. + /// The generalized action will accept any message object which has + /// the same descriptor, and will convert it to the correct class + /// before calling the original action. However, if the generalized + /// callback is given a message with a different descriptor, an + /// exception will be thrown. + /// </summary> + public static Action<IMessage> GeneralizeCallback<TMessage, TBuilder>(Action<TMessage> action, TMessage defaultInstance) + where TMessage : class, IMessage<TMessage, TBuilder> + where TBuilder : IBuilder<TMessage, TBuilder> { + return message => { + TMessage castMessage = message as TMessage; + if (castMessage == null) { + castMessage = defaultInstance.CreateBuilderForType().MergeFrom(message).Build(); + } + action(castMessage); + }; + } + } +} diff --git a/src/ProtocolBuffers/TextFormat.cs b/src/ProtocolBuffers/TextFormat.cs new file mode 100644 index 00000000..d487bd61 --- /dev/null +++ b/src/ProtocolBuffers/TextFormat.cs @@ -0,0 +1,620 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; +using Google.ProtocolBuffers.Descriptors; +using System.Collections; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Provides ASCII text formatting support for messages. + /// TODO(jonskeet): Parsing support. + /// </summary> + public static class TextFormat { + + /// <summary> + /// Outputs a textual representation of the Protocol Message supplied into + /// the parameter output. + /// </summary> + public static void Print(IMessage message, TextWriter output) { + TextGenerator generator = new TextGenerator(output); + Print(message, generator); + } + + /// <summary> + /// Outputs a textual representation of <paramref name="fields" /> to <paramref name="output"/>. + /// </summary> + public static void Print(UnknownFieldSet fields, TextWriter output) { + TextGenerator generator = new TextGenerator(output); + PrintUnknownFields(fields, generator); + } + + public static string PrintToString(IMessage message) { + StringWriter text = new StringWriter(); + Print(message, text); + return text.ToString(); + } + + public static string PrintToString(UnknownFieldSet fields) { + StringWriter text = new StringWriter(); + Print(fields, text); + return text.ToString(); + } + + private static void Print(IMessage message, TextGenerator generator) { + foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields) { + PrintField(entry.Key, entry.Value, generator); + } + PrintUnknownFields(message.UnknownFields, generator); + } + + internal static void PrintField(FieldDescriptor field, object value, TextGenerator generator) { + if (field.IsRepeated) { + // Repeated field. Print each element. + foreach (object element in (IEnumerable) value) { + PrintSingleField(field, element, generator); + } + } else { + PrintSingleField(field, value, generator); + } + } + + private static void PrintSingleField(FieldDescriptor field, Object value, TextGenerator generator) { + if (field.IsExtension) { + generator.Print("["); + // We special-case MessageSet elements for compatibility with proto1. + if (field.ContainingType.Options.MessageSetWireFormat + && field.FieldType == FieldType.Message + && field.IsOptional + // object equality (TODO(jonskeet): Work out what this comment means!) + && field.ExtensionScope == field.MessageType) { + generator.Print(field.MessageType.FullName); + } else { + generator.Print(field.FullName); + } + generator.Print("]"); + } else { + if (field.FieldType == FieldType.Group) { + // Groups must be serialized with their original capitalization. + generator.Print(field.MessageType.Name); + } else { + generator.Print(field.Name); + } + } + + if (field.MappedType == MappedType.Message) { + generator.Print(" {\n"); + generator.Indent(); + } else { + generator.Print(": "); + } + + PrintFieldValue(field, value, generator); + + if (field.MappedType == MappedType.Message) { + generator.Outdent(); + generator.Print("}"); + } + generator.Print("\n"); + } + + private static void PrintFieldValue(FieldDescriptor field, object value, TextGenerator generator) { + switch (field.FieldType) { + case FieldType.Int32: + case FieldType.Int64: + case FieldType.SInt32: + case FieldType.SInt64: + case FieldType.SFixed32: + case FieldType.SFixed64: + case FieldType.Float: + case FieldType.Double: + case FieldType.UInt32: + case FieldType.UInt64: + case FieldType.Fixed32: + case FieldType.Fixed64: + // The simple Object.ToString converts using the current culture. + // We want to always use the invariant culture so it's predictable. + generator.Print(((IConvertible) value).ToString(CultureInfo.InvariantCulture)); + break; + case FieldType.Bool: + // Explicitly use the Java true/false + generator.Print((bool) value ? "true" : "false"); + break; + + case FieldType.String: + generator.Print("\""); + generator.Print(EscapeText((string) value)); + generator.Print("\""); + break; + + case FieldType.Bytes: { + generator.Print("\""); + generator.Print(EscapeBytes((ByteString) value)); + generator.Print("\""); + break; + } + + case FieldType.Enum: { + generator.Print(((EnumValueDescriptor) value).Name); + break; + } + + case FieldType.Message: + case FieldType.Group: + Print((IMessage) value, generator); + break; + } + } + + private static void PrintUnknownFields(UnknownFieldSet unknownFields, TextGenerator generator) { + foreach (KeyValuePair<int, UnknownField> entry in unknownFields.FieldDictionary) { + String prefix = entry.Key.ToString() + ": "; + UnknownField field = entry.Value; + + foreach (ulong value in field.VarintList) { + generator.Print(prefix); + generator.Print(value.ToString()); + generator.Print("\n"); + } + foreach (uint value in field.Fixed32List) { + generator.Print(prefix); + generator.Print(string.Format("0x{0:x8}", value)); + generator.Print("\n"); + } + foreach (ulong value in field.Fixed64List) { + generator.Print(prefix); + generator.Print(string.Format("0x{0:x16}", value)); + generator.Print("\n"); + } + foreach (ByteString value in field.LengthDelimitedList) { + generator.Print(entry.Key.ToString()); + generator.Print(": \""); + generator.Print(EscapeBytes(value)); + generator.Print("\"\n"); + } + foreach (UnknownFieldSet value in field.GroupList) { + generator.Print(entry.Key.ToString()); + generator.Print(" {\n"); + generator.Indent(); + PrintUnknownFields(value, generator); + generator.Outdent(); + generator.Print("}\n"); + } + } + } + + internal static ulong ParseUInt64(string text) { + return (ulong) ParseInteger(text, false, true); + } + + internal static long ParseInt64(string text) { + return ParseInteger(text, true, true); + } + + internal static uint ParseUInt32(string text) { + return (uint) ParseInteger(text, false, false); + } + + internal static int ParseInt32(string text) { + return (int) ParseInteger(text, true, false); + } + + /// <summary> + /// Parses an integer in hex (leading 0x), decimal (no prefix) or octal (leading 0). + /// Only a negative sign is permitted, and it must come before the radix indicator. + /// </summary> + private static long ParseInteger(string text, bool isSigned, bool isLong) { + string original = text; + bool negative = false; + if (text.StartsWith("-")) { + if (!isSigned) { + throw new FormatException("Number must be positive: " + original); + } + negative = true; + text = text.Substring(1); + } + + int radix = 10; + if (text.StartsWith("0x")) { + radix = 16; + text = text.Substring(2); + } else if (text.StartsWith("0")) { + radix = 8; + } + + ulong result; + try { + // Workaround for https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448 + // We should be able to use Convert.ToUInt64 for all cases. + result = radix == 10 ? ulong.Parse(text) : Convert.ToUInt64(text, radix); + } catch (OverflowException) { + // Convert OverflowException to FormatException so there's a single exception type this method can throw. + string numberDescription = string.Format("{0}-bit {1}signed integer", isLong ? 64 : 32, isSigned ? "" : "un"); + throw new FormatException("Number out of range for " + numberDescription + ": " + original); + } + + if (negative) { + ulong max = isLong ? 0x8000000000000000UL : 0x80000000L; + if (result > max) { + string numberDescription = string.Format("{0}-bit signed integer", isLong ? 64 : 32); + throw new FormatException("Number out of range for " + numberDescription + ": " + original); + } + return -((long) result); + } else { + ulong max = isSigned + ? (isLong ? (ulong) long.MaxValue : int.MaxValue) + : (isLong ? ulong.MaxValue : uint.MaxValue); + if (result > max) { + string numberDescription = string.Format("{0}-bit {1}signed integer", isLong ? 64 : 32, isSigned ? "" : "un"); + throw new FormatException("Number out of range for " + numberDescription + ": " + original); + } + return (long) result; + } + } + + /// <summary> + /// Tests a character to see if it's an octal digit. + /// </summary> + private static bool IsOctal(char c) { + return '0' <= c && c <= '7'; + } + + /// <summary> + /// Tests a character to see if it's a hex digit. + /// </summary> + private static bool IsHex(char c) { + return ('0' <= c && c <= '9') || + ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F'); + } + + /// <summary> + /// Interprets a character as a digit (in any base up to 36) and returns the + /// numeric value. + /// </summary> + private static int ParseDigit(char c) { + if ('0' <= c && c <= '9') { + return c - '0'; + } else if ('a' <= c && c <= 'z') { + return c - 'a' + 10; + } else { + return c - 'A' + 10; + } + } + + /// <summary> + /// Unescapes a text string as escaped using <see cref="EscapeText(string)" />. + /// Two-digit hex escapes (starting with "\x" are also recognised. + /// </summary> + internal static string UnescapeText(string input) { + return UnescapeBytes(input).ToStringUtf8(); + } + + /// <summary> + /// Like <see cref="EscapeBytes" /> but escapes a text string. + /// The string is first encoded as UTF-8, then each byte escaped individually. + /// The returned value is guaranteed to be entirely ASCII. + /// </summary> + internal static string EscapeText(string input) { + return EscapeBytes(ByteString.CopyFromUtf8(input)); + } + + /// <summary> + /// Escapes bytes in the format used in protocol buffer text format, which + /// is the same as the format used for C string literals. All bytes + /// that are not printable 7-bit ASCII characters are escaped, as well as + /// backslash, single-quote, and double-quote characters. Characters for + /// which no defined short-hand escape sequence is defined will be escaped + /// using 3-digit octal sequences. + /// The returned value is guaranteed to be entirely ASCII. + /// </summary> + internal static String EscapeBytes(ByteString input) { + StringBuilder builder = new StringBuilder(input.Length); + foreach (byte b in input) { + switch (b) { + // C# does not use \a or \v + case 0x07: builder.Append("\\a" ); break; + case (byte)'\b': builder.Append("\\b" ); break; + case (byte)'\f': builder.Append("\\f" ); break; + case (byte)'\n': builder.Append("\\n" ); break; + case (byte)'\r': builder.Append("\\r" ); break; + case (byte)'\t': builder.Append("\\t" ); break; + case 0x0b: builder.Append("\\v" ); break; + case (byte)'\\': builder.Append("\\\\"); break; + case (byte)'\'': builder.Append("\\\'"); break; + case (byte)'"' : builder.Append("\\\""); break; + default: + if (b >= 0x20 && b < 128) { + builder.Append((char) b); + } else { + builder.Append('\\'); + builder.Append((char) ('0' + ((b >> 6) & 3))); + builder.Append((char) ('0' + ((b >> 3) & 7))); + builder.Append((char) ('0' + (b & 7))); + } + break; + } + } + return builder.ToString(); + } + + /// <summary> + /// Performs string unescaping from C style (octal, hex, form feeds, tab etc) into a byte string. + /// </summary> + internal static ByteString UnescapeBytes(string input) { + byte[] result = new byte[input.Length]; + int pos = 0; + for (int i = 0; i < input.Length; i++) { + char c = input[i]; + if (c > 127 || c < 32) { + throw new FormatException("Escaped string must only contain ASCII"); + } + if (c != '\\') { + result[pos++] = (byte) c; + continue; + } + if (i + 1 >= input.Length) { + throw new FormatException("Invalid escape sequence: '\\' at end of string."); + } + + i++; + c = input[i]; + if (c >= '0' && c <= '7') { + // Octal escape. + int code = ParseDigit(c); + if (i + 1 < input.Length && IsOctal(input[i+1])) { + i++; + code = code * 8 + ParseDigit(input[i]); + } + if (i + 1 < input.Length && IsOctal(input[i+1])) { + i++; + code = code * 8 + ParseDigit(input[i]); + } + result[pos++] = (byte) code; + } else { + switch (c) { + case 'a': result[pos++] = 0x07; break; + case 'b': result[pos++] = (byte) '\b'; break; + case 'f': result[pos++] = (byte) '\f'; break; + case 'n': result[pos++] = (byte) '\n'; break; + case 'r': result[pos++] = (byte) '\r'; break; + case 't': result[pos++] = (byte) '\t'; break; + case 'v': result[pos++] = 0x0b; break; + case '\\': result[pos++] = (byte) '\\'; break; + case '\'': result[pos++] = (byte) '\''; break; + case '"': result[pos++] = (byte) '\"'; break; + + case 'x': + // hex escape + int code; + if (i + 1 < input.Length && IsHex(input[i+1])) { + i++; + code = ParseDigit(input[i]); + } else { + throw new FormatException("Invalid escape sequence: '\\x' with no digits"); + } + if (i + 1 < input.Length && IsHex(input[i+1])) { + ++i; + code = code * 16 + ParseDigit(input[i]); + } + result[pos++] = (byte)code; + break; + + default: + throw new FormatException("Invalid escape sequence: '\\" + c + "'"); + } + } + } + + return ByteString.CopyFrom(result, 0, pos); + } + + public static void Merge(string text, IBuilder builder) { + Merge(text, ExtensionRegistry.Empty, builder); + } + + public static void Merge(TextReader reader, IBuilder builder) { + Merge(reader, ExtensionRegistry.Empty, builder); + } + + public static void Merge(TextReader reader, ExtensionRegistry registry, IBuilder builder) { + Merge(reader.ReadToEnd(), registry, builder); + } + + public static void Merge(string text, ExtensionRegistry registry, IBuilder builder) { + TextTokenizer tokenizer = new TextTokenizer(text); + + while (!tokenizer.AtEnd) { + MergeField(tokenizer, registry, builder); + } + } + + /// <summary> + /// Parses a single field from the specified tokenizer and merges it into + /// the builder. + /// </summary> + private static void MergeField(TextTokenizer tokenizer, ExtensionRegistry extensionRegistry, + IBuilder builder) { + + FieldDescriptor field; + MessageDescriptor type = builder.DescriptorForType; + ExtensionInfo extension = null; + + if (tokenizer.TryConsume("[")) { + // An extension. + StringBuilder name = new StringBuilder(tokenizer.ConsumeIdentifier()); + while (tokenizer.TryConsume(".")) { + name.Append("."); + name.Append(tokenizer.ConsumeIdentifier()); + } + + extension = extensionRegistry[name.ToString()]; + + if (extension == null) { + throw tokenizer.CreateFormatExceptionPreviousToken("Extension \"" + name + "\" not found in the ExtensionRegistry."); + } else if (extension.Descriptor.ContainingType != type) { + throw tokenizer.CreateFormatExceptionPreviousToken("Extension \"" + name + "\" does not extend message type \"" + + type.FullName + "\"."); + } + + tokenizer.Consume("]"); + + field = extension.Descriptor; + } else { + String name = tokenizer.ConsumeIdentifier(); + field = type.FindDescriptor<FieldDescriptor>(name); + + // Group names are expected to be capitalized as they appear in the + // .proto file, which actually matches their type names, not their field + // names. + if (field == null) { + // Explicitly specify the invariant culture so that this code does not break when + // executing in Turkey. + String lowerName = name.ToLowerInvariant(); + field = type.FindDescriptor<FieldDescriptor>(lowerName); + // If the case-insensitive match worked but the field is NOT a group, + // TODO(jonskeet): What? Java comment ends here! + if (field != null && field.FieldType != FieldType.Group) { + field = null; + } + } + // Again, special-case group names as described above. + if (field != null && field.FieldType == FieldType.Group && field.MessageType.Name != name) { + field = null; + } + + if (field == null) { + throw tokenizer.CreateFormatExceptionPreviousToken( + "Message type \"" + type.FullName + "\" has no field named \"" + name + "\"."); + } + } + + object value = null; + + if (field.MappedType == MappedType.Message) { + tokenizer.TryConsume(":"); // optional + + String endToken; + if (tokenizer.TryConsume("<")) { + endToken = ">"; + } else { + tokenizer.Consume("{"); + endToken = "}"; + } + + IBuilder subBuilder; + if (extension == null) { + subBuilder = builder.CreateBuilderForField(field); + } else { + subBuilder = extension.DefaultInstance.WeakCreateBuilderForType(); + } + + while (!tokenizer.TryConsume(endToken)) { + if (tokenizer.AtEnd) { + throw tokenizer.CreateFormatException("Expected \"" + endToken + "\"."); + } + MergeField(tokenizer, extensionRegistry, subBuilder); + } + + value = subBuilder.WeakBuild(); + + } else { + tokenizer.Consume(":"); + + switch (field.FieldType) { + case FieldType.Int32: + case FieldType.SInt32: + case FieldType.SFixed32: + value = tokenizer.ConsumeInt32(); + break; + + case FieldType.Int64: + case FieldType.SInt64: + case FieldType.SFixed64: + value = tokenizer.ConsumeInt64(); + break; + + case FieldType.UInt32: + case FieldType.Fixed32: + value = tokenizer.ConsumeUInt32(); + break; + + case FieldType.UInt64: + case FieldType.Fixed64: + value = tokenizer.ConsumeUInt64(); + break; + + case FieldType.Float: + value = tokenizer.ConsumeFloat(); + break; + + case FieldType.Double: + value = tokenizer.ConsumeDouble(); + break; + + case FieldType.Bool: + value = tokenizer.ConsumeBoolean(); + break; + + case FieldType.String: + value = tokenizer.ConsumeString(); + break; + + case FieldType.Bytes: + value = tokenizer.ConsumeByteString(); + break; + + case FieldType.Enum: { + EnumDescriptor enumType = field.EnumType; + + if (tokenizer.LookingAtInteger()) { + int number = tokenizer.ConsumeInt32(); + value = enumType.FindValueByNumber(number); + if (value == null) { + throw tokenizer.CreateFormatExceptionPreviousToken( + "Enum type \"" + enumType.FullName + + "\" has no value with number " + number + "."); + } + } else { + String id = tokenizer.ConsumeIdentifier(); + value = enumType.FindValueByName(id); + if (value == null) { + throw tokenizer.CreateFormatExceptionPreviousToken( + "Enum type \"" + enumType.FullName + + "\" has no value named \"" + id + "\"."); + } + } + + break; + } + + case FieldType.Message: + case FieldType.Group: + throw new InvalidOperationException("Can't get here."); + } + } + + if (field.IsRepeated) { + builder.WeakAddRepeatedField(field, value); + } else { + builder.SetField(field, value); + } + } + } +} diff --git a/src/ProtocolBuffers/TextGenerator.cs b/src/ProtocolBuffers/TextGenerator.cs new file mode 100644 index 00000000..fb0f66dd --- /dev/null +++ b/src/ProtocolBuffers/TextGenerator.cs @@ -0,0 +1,115 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.IO; +using System.Text; + +namespace Google.ProtocolBuffers { + + /// <summary> + /// Helper class to control indentation. Used for TextFormat and by ProtoGen. + /// </summary> + public sealed class TextGenerator { + + /// <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> + bool atStartOfLine = true; + + /// <summary> + /// Keeps track of the current level of indentation + /// </summary> + 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) { + this.writer = writer; + } + + /// <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') { + // TODO(jonskeet): Use Environment.NewLine? + Write(text.Substring(pos, i - pos + 1)); + 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); + } + } +} diff --git a/src/ProtocolBuffers/TextTokenizer.cs b/src/ProtocolBuffers/TextTokenizer.cs new file mode 100644 index 00000000..d53ae596 --- /dev/null +++ b/src/ProtocolBuffers/TextTokenizer.cs @@ -0,0 +1,390 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Represents a stream of tokens parsed from a string. + /// </summary> + internal sealed class TextTokenizer { + private readonly string text; + private string currentToken; + + /// <summary> + /// The character index within the text to perform the next regex match at. + /// </summary> + private int matchPos = 0; + + /// <summary> + /// The character index within the text at which the current token begins. + /// </summary> + private int pos = 0; + + /// <summary> + /// The line number of the current token. + /// </summary> + private int line = 0; + /// <summary> + /// The column number of the current token. + /// </summary> + private int column = 0; + + /// <summary> + /// The line number of the previous token. + /// </summary> + private int previousLine = 0; + /// <summary> + /// The column number of the previous token. + /// </summary> + private int previousColumn = 0; + + private static readonly Regex WhitespaceAndCommentPattern = new Regex("\\G(\\s|(#.*$))+", + RegexOptions.Compiled | RegexOptions.Multiline); + private static readonly Regex TokenPattern = new Regex( + "\\G[a-zA-Z_][0-9a-zA-Z_+-]*|" + // an identifier + "\\G[0-9+-][0-9a-zA-Z_.+-]*|" + // a number + "\\G\"([^\"\\\n\\\\]|\\\\.)*(\"|\\\\?$)|" + // a double-quoted string + "\\G\'([^\"\\\n\\\\]|\\\\.)*(\'|\\\\?$)", // a single-quoted string + RegexOptions.Compiled | RegexOptions.Multiline); + + private static readonly Regex DoubleInfinity = new Regex("^-?inf(inity)?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex FloatInfinity = new Regex("^-?inf(inity)?f?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex FloatNan = new Regex("^nanf?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); + + /** Construct a tokenizer that parses tokens from the given text. */ + public TextTokenizer(string text) { + this.text = text; + SkipWhitespace(); + NextToken(); + } + + /// <summary> + /// Are we at the end of the input? + /// </summary> + public bool AtEnd { + get { return currentToken.Length == 0; } + } + + /// <summary> + /// Advances to the next token. + /// </summary> + public void NextToken() { + previousLine = line; + previousColumn = column; + + // Advance the line counter to the current position. + while (pos < matchPos) { + if (text[pos] == '\n') { + ++line; + column = 0; + } else { + ++column; + } + ++pos; + } + + // Match the next token. + if (matchPos == text.Length) { + // EOF + currentToken = ""; + } else { + Match match = TokenPattern.Match(text, matchPos); + if (match.Success) { + currentToken = match.Value; + matchPos += match.Length; + } else { + // Take one character. + currentToken = text[matchPos].ToString(); + matchPos++; + } + + SkipWhitespace(); + } + } + + /// <summary> + /// Skip over any whitespace so that matchPos starts at the next token. + /// </summary> + private void SkipWhitespace() { + Match match = WhitespaceAndCommentPattern.Match(text, matchPos); + if (match.Success) { + matchPos += match.Length; + } + } + + /// <summary> + /// If the next token exactly matches the given token, consume it and return + /// true. Otherwise, return false without doing anything. + /// </summary> + public bool TryConsume(string token) { + if (currentToken == token) { + NextToken(); + return true; + } + return false; + } + + /* + * If the next token exactly matches {@code token}, consume it. Otherwise, + * throw a {@link ParseException}. + */ + /// <summary> + /// If the next token exactly matches the specified one, consume it. + /// Otherwise, throw a FormatException. + /// </summary> + /// <param name="token"></param> + public void Consume(string token) { + if (!TryConsume(token)) { + throw CreateFormatException("Expected \"" + token + "\"."); + } + } + + /// <summary> + /// Returns true if the next token is an integer, but does not consume it. + /// </summary> + public bool LookingAtInteger() { + if (currentToken.Length == 0) { + return false; + } + + char c = currentToken[0]; + return ('0' <= c && c <= '9') || c == '-' || c == '+'; + } + + /// <summary> + /// If the next token is an identifier, consume it and return its value. + /// Otherwise, throw a FormatException. + /// </summary> + public string ConsumeIdentifier() { + foreach (char c in currentToken) { + if (('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9') || + (c == '_') || (c == '.')) { + // OK + } else { + throw CreateFormatException("Expected identifier."); + } + } + + string result = currentToken; + NextToken(); + return result; + } + + /// <summary> + /// If the next token is a 32-bit signed integer, consume it and return its + /// value. Otherwise, throw a FormatException. + /// </summary> + public int ConsumeInt32() { + try { + int result = TextFormat.ParseInt32(currentToken); + NextToken(); + return result; + } catch (FormatException e) { + throw CreateIntegerParseException(e); + } + } + + /// <summary> + /// If the next token is a 32-bit unsigned integer, consume it and return its + /// value. Otherwise, throw a FormatException. + /// </summary> + public uint ConsumeUInt32() { + try { + uint result = TextFormat.ParseUInt32(currentToken); + NextToken(); + return result; + } catch (FormatException e) { + throw CreateIntegerParseException(e); + } + } + + /// <summary> + /// If the next token is a 64-bit signed integer, consume it and return its + /// value. Otherwise, throw a FormatException. + /// </summary> + public long ConsumeInt64() { + try { + long result = TextFormat.ParseInt64(currentToken); + NextToken(); + return result; + } catch (FormatException e) { + throw CreateIntegerParseException(e); + } + } + + /// <summary> + /// If the next token is a 64-bit unsigned integer, consume it and return its + /// value. Otherwise, throw a FormatException. + /// </summary> + public ulong ConsumeUInt64() { + try { + ulong result = TextFormat.ParseUInt64(currentToken); + NextToken(); + return result; + } catch (FormatException e) { + throw CreateIntegerParseException(e); + } + } + + /// <summary> + /// If the next token is a double, consume it and return its value. + /// Otherwise, throw a FormatException. + /// </summary> + public double ConsumeDouble() { + // We need to parse infinity and nan separately because + // double.Parse() does not accept "inf", "infinity", or "nan". + if (DoubleInfinity.IsMatch(currentToken)) { + bool negative = currentToken.StartsWith("-"); + NextToken(); + return negative ? double.NegativeInfinity : double.PositiveInfinity; + } + if (currentToken.Equals("nan", StringComparison.InvariantCultureIgnoreCase)) { + NextToken(); + return Double.NaN; + } + + try { + double result = double.Parse(currentToken, CultureInfo.InvariantCulture); + NextToken(); + return result; + } catch (FormatException e) { + throw CreateFloatParseException(e); + } catch (OverflowException e) { + throw CreateFloatParseException(e); + } + } + + /// <summary> + /// If the next token is a float, consume it and return its value. + /// Otherwise, throw a FormatException. + /// </summary> + public float ConsumeFloat() { + + // We need to parse infinity and nan separately because + // Float.parseFloat() does not accept "inf", "infinity", or "nan". + if (FloatInfinity.IsMatch(currentToken)) { + bool negative = currentToken.StartsWith("-"); + NextToken(); + return negative ? float.NegativeInfinity : float.PositiveInfinity; + } + if (FloatNan.IsMatch(currentToken)) { + NextToken(); + return float.NaN; + } + + if (currentToken.EndsWith("f")) { + currentToken = currentToken.TrimEnd('f'); + } + + try { + float result = float.Parse(currentToken, CultureInfo.InvariantCulture); + NextToken(); + return result; + } catch (FormatException e) { + throw CreateFloatParseException(e); + } catch (OverflowException e) { + throw CreateFloatParseException(e); + } + } + + /// <summary> + /// If the next token is a Boolean, consume it and return its value. + /// Otherwise, throw a FormatException. + /// </summary> + public bool ConsumeBoolean() { + if (currentToken == "true") { + NextToken(); + return true; + } + if (currentToken == "false") { + NextToken(); + return false; + } + throw CreateFormatException("Expected \"true\" or \"false\"."); + } + + /// <summary> + /// If the next token is a string, consume it and return its (unescaped) value. + /// Otherwise, throw a FormatException. + /// </summary> + public string ConsumeString() { + return ConsumeByteString().ToStringUtf8(); + } + + /// <summary> + /// If the next token is a string, consume it, unescape it as a + /// ByteString and return it. Otherwise, throw a FormatException. + /// </summary> + public ByteString ConsumeByteString() { + char quote = currentToken.Length > 0 ? currentToken[0] : '\0'; + if (quote != '\"' && quote != '\'') { + throw CreateFormatException("Expected string."); + } + + if (currentToken.Length < 2 || + currentToken[currentToken.Length-1] != quote) { + throw CreateFormatException("String missing ending quote."); + } + + try { + string escaped = currentToken.Substring(1, currentToken.Length - 2); + ByteString result = TextFormat.UnescapeBytes(escaped); + NextToken(); + return result; + } catch (FormatException e) { + throw CreateFormatException(e.Message); + } + } + + /// <summary> + /// Returns a format exception with the current line and column numbers + /// in the description, suitable for throwing. + /// </summary> + public FormatException CreateFormatException(string description) { + // Note: People generally prefer one-based line and column numbers. + return new FormatException((line + 1) + ":" + (column + 1) + ": " + description); + } + + /// <summary> + /// Returns a format exception with the line and column numbers of the + /// previous token in the description, suitable for throwing. + /// </summary> + public FormatException CreateFormatExceptionPreviousToken(string description) { + // Note: People generally prefer one-based line and column numbers. + return new FormatException((previousLine + 1) + ":" + (previousColumn + 1) + ": " + description); + } + + /// <summary> + /// Constructs an appropriate FormatException for the given existing exception + /// when trying to parse an integer. + /// </summary> + private FormatException CreateIntegerParseException(FormatException e) { + return CreateFormatException("Couldn't parse integer: " + e.Message); + } + + /// <summary> + /// Constructs an appropriate FormatException for the given existing exception + /// when trying to parse a float or double. + /// </summary> + private FormatException CreateFloatParseException(Exception e) { + return CreateFormatException("Couldn't parse number: " + e.Message); + } + } +} diff --git a/src/ProtocolBuffers/UninitializedMessageException.cs b/src/ProtocolBuffers/UninitializedMessageException.cs new file mode 100644 index 00000000..b0d601bd --- /dev/null +++ b/src/ProtocolBuffers/UninitializedMessageException.cs @@ -0,0 +1,127 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + /// <summary> + /// TODO(jonskeet): Write summary text. + /// </summary> + public sealed class UninitializedMessageException : Exception { + + private readonly IList<string> missingFields; + + public UninitializedMessageException(IMessage message) + : this(FindMissingFields(message)) { + } + + private UninitializedMessageException(IList<string> missingFields) + : base(BuildDescription(missingFields)) { + this.missingFields = Lists.AsReadOnly(missingFields); + } + + + /// <summary> + /// Converts this exception into an InvalidProtocolBufferException. + /// When a parsed message is missing required fields, this should be thrown + /// instead of UninitializedMessageException. + /// </summary> + public InvalidProtocolBufferException AsInvalidProtocolBufferException() { + return new InvalidProtocolBufferException(Message); + } + + /// <summary> + /// Constructs the description string for a given list of missing fields. + /// </summary> + private static string BuildDescription(IEnumerable<string> missingFields) { + StringBuilder description = new StringBuilder("Message missing required fields: "); + bool first = true; + foreach(string field in missingFields) { + if (first) { + first = false; + } else { + description.Append(", "); + } + description.Append(field); + } + return description.ToString(); + } + + /// <summary> + /// Returns a list of the full "paths" of missing required + /// fields in the specified message. + /// </summary> + private static IList<String> FindMissingFields(IMessage message) { + List<String> results = new List<String>(); + FindMissingFields(message, "", results); + return results; + } + + /// <summary> + /// Recursive helper implementing FindMissingFields. + /// </summary> + private static void FindMissingFields(IMessage message, String prefix, List<String> results) { + foreach (FieldDescriptor field in message.DescriptorForType.Fields) { + if (field.IsRequired && !message.HasField(field)) { + results.Add(prefix + field.Name); + } + } + + foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields) { + FieldDescriptor field = entry.Key; + object value = entry.Value; + + if (field.MappedType == MappedType.Message) { + if (field.IsRepeated) { + int i = 0; + foreach (object element in (IEnumerable) value) { + FindMissingFields((IMessage) element, SubMessagePrefix(prefix, field, i++), results); + } + } else { + if (message.HasField(field)) { + FindMissingFields((IMessage) value, SubMessagePrefix(prefix, field, -1), results); + } + } + } + } + } + + private static String SubMessagePrefix(String prefix, FieldDescriptor field, int index) { + StringBuilder result = new StringBuilder(prefix); + if (field.IsExtension) { + result.Append('(') + .Append(field.FullName) + .Append(')'); + } else { + result.Append(field.Name); + } + if (index != -1) { + result.Append('[') + .Append(index) + .Append(']'); + } + result.Append('.'); + return result.ToString(); + } + } +} + + + diff --git a/src/ProtocolBuffers/UnknownField.cs b/src/ProtocolBuffers/UnknownField.cs new file mode 100644 index 00000000..76afe680 --- /dev/null +++ b/src/ProtocolBuffers/UnknownField.cs @@ -0,0 +1,321 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Google.ProtocolBuffers.Collections; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Represents a single field in an UnknownFieldSet. + /// + /// An UnknownField consists of five lists of values. The lists correspond + /// to the five "wire types" used in the protocol buffer binary format. + /// The wire type of each field can be determined from the encoded form alone, + /// without knowing the field's declared type. So, we are able to parse + /// unknown values at least this far and separate them. Normally, only one + /// of the five lists will contain any values, since it is impossible to + /// define a valid message type that declares two different types for the + /// same field number. However, the code is designed to allow for the case + /// where the same unknown field number is encountered using multiple different + /// wire types. + /// + /// UnknownField is an immutable class. To construct one, you must use an + /// UnknownField.Builder. + /// </summary> + public sealed class UnknownField { + + private static readonly UnknownField defaultInstance = CreateBuilder().Build(); + private readonly ReadOnlyCollection<ulong> varintList; + private readonly ReadOnlyCollection<uint> fixed32List; + private readonly ReadOnlyCollection<ulong> fixed64List; + private readonly ReadOnlyCollection<ByteString> lengthDelimitedList; + private readonly ReadOnlyCollection<UnknownFieldSet> groupList; + + private UnknownField(ReadOnlyCollection<ulong> varintList, + ReadOnlyCollection<uint> fixed32List, + ReadOnlyCollection<ulong> fixed64List, + ReadOnlyCollection<ByteString> lengthDelimitedList, + ReadOnlyCollection<UnknownFieldSet> groupList) { + this.varintList = varintList; + this.fixed32List = fixed32List; + this.fixed64List = fixed64List; + this.lengthDelimitedList = lengthDelimitedList; + this.groupList = groupList; + } + + public static UnknownField DefaultInstance { + get { return defaultInstance; } + } + + /// <summary> + /// The list of varint values for this field. + /// </summary> + public IList<ulong> VarintList { + get { return varintList; } + } + + /// <summary> + /// The list of fixed32 values for this field. + /// </summary> + public IList<uint> Fixed32List { + get { return fixed32List; } + } + + /// <summary> + /// The list of fixed64 values for this field. + /// </summary> + public IList<ulong> Fixed64List { + get { return fixed64List; } + } + + /// <summary> + /// The list of length-delimited values for this field. + /// </summary> + public IList<ByteString> LengthDelimitedList { + get { return lengthDelimitedList; } + } + + /// <summary> + /// The list of embedded group values for this field. These + /// are represented using UnknownFieldSets rather than Messages + /// since the group's type is presumably unknown. + /// </summary> + public IList<UnknownFieldSet> GroupList { + get { return groupList; } + } + + /// <summary> + /// Constructs a new Builder. + /// </summary> + public static Builder CreateBuilder() { + return new Builder(); + } + + /// <summary> + /// Constructs a new Builder and initializes it to a copy of <paramref name="copyFrom"/>. + /// </summary> + public static Builder CreateBuilder(UnknownField copyFrom) { + return new Builder().MergeFrom(copyFrom); + } + + /// <summary> + /// Serializes the field, including the field number, and writes it to + /// <paramref name="output"/>. + /// </summary> + public void WriteTo(int fieldNumber, CodedOutputStream output) { + foreach (ulong value in varintList) { + output.WriteUInt64(fieldNumber, value); + } + foreach (uint value in fixed32List) { + output.WriteFixed32(fieldNumber, value); + } + foreach (ulong value in fixed64List) { + output.WriteFixed64(fieldNumber, value); + } + foreach (ByteString value in lengthDelimitedList) { + output.WriteBytes(fieldNumber, value); + } + foreach (UnknownFieldSet value in groupList) { + output.WriteUnknownGroup(fieldNumber, value); + } + } + + /// <summary> + /// Computes the number of bytes required to encode this field, including field + /// number. + /// </summary> + public int GetSerializedSize(int fieldNumber) { + int result = 0; + foreach (ulong value in varintList) { + result += CodedOutputStream.ComputeUInt64Size(fieldNumber, value); + } + foreach (uint value in fixed32List) { + result += CodedOutputStream.ComputeFixed32Size(fieldNumber, value); + } + foreach (ulong value in fixed64List) { + result += CodedOutputStream.ComputeFixed64Size(fieldNumber, value); + } + foreach (ByteString value in lengthDelimitedList) { + result += CodedOutputStream.ComputeBytesSize(fieldNumber, value); + } + foreach (UnknownFieldSet value in groupList) { + result += CodedOutputStream.ComputeUnknownGroupSize(fieldNumber, value); + } + return result; + } + + /// <summary> + /// Serializes the length-delimited values of the field, including field + /// number, and writes them to <paramref name="output"/> using the MessageSet wire format. + /// </summary> + /// <param name="fieldNumber"></param> + /// <param name="output"></param> + public void WriteAsMessageSetExtensionTo(int fieldNumber, CodedOutputStream output) { + foreach (ByteString value in lengthDelimitedList) { + output.WriteRawMessageSetExtension(fieldNumber, value); + } + } + + /// <summary> + /// Get the number of bytes required to encode this field, incuding field number, + /// using the MessageSet wire format. + /// </summary> + public int GetSerializedSizeAsMessageSetExtension(int fieldNumber) { + int result = 0; + foreach (ByteString value in lengthDelimitedList) { + result += CodedOutputStream.ComputeRawMessageSetExtensionSize(fieldNumber, value); + } + return result; + } + + /// <summary> + /// Used to build instances of UnknownField. + /// </summary> + public sealed class Builder { + + private List<ulong> varintList; + private List<uint> fixed32List; + private List<ulong> fixed64List; + private List<ByteString> lengthDelimitedList; + private List<UnknownFieldSet> groupList; + + /// <summary> + /// Builds the field. After building, the builder is reset to an empty + /// state. (This is actually easier than making it unusable.) + /// </summary> + public UnknownField Build() { + return new UnknownField(MakeReadOnly(ref varintList), + MakeReadOnly(ref fixed32List), + MakeReadOnly(ref fixed64List), + MakeReadOnly(ref lengthDelimitedList), + MakeReadOnly(ref groupList)); + } + + /// <summary> + /// Merge the values in <paramref name="other" /> into this field. For each list + /// of values, <paramref name="other"/>'s values are append to the ones in this + /// field. + /// </summary> + public Builder MergeFrom(UnknownField other) { + varintList = AddAll(varintList, other.VarintList); + fixed32List = AddAll(fixed32List, other.Fixed32List); + fixed64List = AddAll(fixed64List, other.Fixed64List); + lengthDelimitedList = AddAll(lengthDelimitedList, other.LengthDelimitedList); + groupList = AddAll(groupList, other.GroupList); + return this; + } + + /// <summary> + /// Returns a new list containing all of the given specified values from + /// both the <paramref name="current"/> and <paramref name="extras"/> lists. + /// If <paramref name="current" /> is null and <paramref name="extras"/> is empty, + /// null is returned. Otherwise, either a new list is created (if <paramref name="current" /> + /// is null) or the elements of <paramref name="extras"/> are added to <paramref name="current" />. + /// </summary> + private static List<T> AddAll<T>(List<T> current, IList<T> extras) + { + if (extras.Count == 0) { + return current; + } + if (current == null) { + current = new List<T>(extras); + } else { + current.AddRange(extras); + } + return current; + } + + /// <summary> + /// Clears the contents of this builder. + /// </summary> + public Builder Clear() { + varintList = null; + fixed32List = null; + fixed64List = null; + lengthDelimitedList = null; + groupList = null; + return this; + } + + /// <summary> + /// Adds a varint value. + /// </summary> + public Builder AddVarint(ulong value) { + varintList = Add(varintList, value); + return this; + } + + /// <summary> + /// Adds a fixed32 value. + /// </summary> + public Builder AddFixed32(uint value) { + fixed32List = Add(fixed32List, value); + return this; + } + + /// <summary> + /// Adds a fixed64 value. + /// </summary> + public Builder AddFixed64(ulong value) { + fixed64List = Add(fixed64List, value); + return this; + } + + /// <summary> + /// Adds a length-delimited value. + /// </summary> + public Builder AddLengthDelimited(ByteString value) { + lengthDelimitedList = Add(lengthDelimitedList, value); + return this; + } + + /// <summary> + /// Adds an embedded group. + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + public Builder AddGroup(UnknownFieldSet value) { + groupList = Add(groupList, value); + return this; + } + + /// <summary> + /// Adds <paramref name="value"/> to the <paramref name="list"/>, creating + /// a new list if <paramref name="list"/> is null. The list is returned - either + /// the original reference or the new list. + /// </summary> + private static List<T> Add<T>(List<T> list, T value) { + if (list == null) { + list = new List<T>(); + } + list.Add(value); + return list; + } + + /// <summary> + /// Returns a read-only version of the given IList, and clears + /// the field used for <paramref name="list"/>. If the value + /// is null, an empty list is produced using Lists.Empty. + /// </summary> + /// <returns></returns> + private static ReadOnlyCollection<T> MakeReadOnly<T>(ref List<T> list) { + ReadOnlyCollection<T> ret = list == null ? Lists<T>.Empty : new ReadOnlyCollection<T>(list); + list = null; + return ret; + } + } + } +} diff --git a/src/ProtocolBuffers/UnknownFieldSet.cs b/src/ProtocolBuffers/UnknownFieldSet.cs new file mode 100644 index 00000000..18eacbe8 --- /dev/null +++ b/src/ProtocolBuffers/UnknownFieldSet.cs @@ -0,0 +1,626 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Generic; +using System.IO; +using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.Descriptors; +using Google.ProtocolBuffers.DescriptorProtos; + +namespace Google.ProtocolBuffers { + /// <summary> + /// Used to keep track of fields which were seen when parsing a protocol message + /// but whose field numbers or types are unrecognized. This most frequently + /// occurs when new fields are added to a message type and then messages containing + /// those fields are read by old software that was built before the new types were + /// added. + /// + /// Every message contains an UnknownFieldSet. + /// + /// Most users will never need to use this class directly. + /// </summary> + public sealed class UnknownFieldSet { + + private static readonly UnknownFieldSet defaultInstance = new UnknownFieldSet(new Dictionary<int, UnknownField>()); + + private readonly IDictionary<int, UnknownField> fields; + + private UnknownFieldSet(IDictionary<int, UnknownField> fields) { + this.fields = fields; + } + + /// <summary> + /// Creates a new unknown field set builder. + /// </summary> + public static Builder CreateBuilder() { + return new Builder(); + } + + /// <summary> + /// Creates a new unknown field set builder + /// and initialize it from <paramref name="original"/>. + /// </summary> + public static Builder CreateBuilder(UnknownFieldSet original) { + return new Builder().MergeFrom(original); + } + + public static UnknownFieldSet DefaultInstance { + get { return defaultInstance; } + } + + /// <summary> + /// Returns a read-only view of the mapping from field numbers to values. + /// </summary> + public IDictionary<int, UnknownField> FieldDictionary { + get { return Dictionaries.AsReadOnly(fields); } + } + + /// <summary> + /// Checks whether or not the given field number is present in the set. + /// </summary> + public bool HasField(int field) { + return fields.ContainsKey(field); + } + + /// <summary> + /// Fetches a field by number, returning an empty field if not present. + /// Never returns null. + /// </summary> + public UnknownField this[int number] { + get { + UnknownField ret; + if (!fields.TryGetValue(number, out ret)) { + ret = UnknownField.DefaultInstance; + } + return ret; + } + } + + /// <summary> + /// Serializes the set and writes it to <paramref name="output"/>. + /// </summary> + public void WriteTo(CodedOutputStream output) { + foreach (KeyValuePair<int, UnknownField> entry in fields) { + entry.Value.WriteTo(entry.Key, output); + } + } + + /// <summary> + /// Gets the number of bytes required to encode this set. + /// </summary> + public int SerializedSize { + get { + int result = 0; + foreach (KeyValuePair<int, UnknownField> entry in fields) { + result += entry.Value.GetSerializedSize(entry.Key); + } + return result; + } + } + + /// <summary> + /// Converts the set to a string in protocol buffer text format. This + /// is just a trivial wrapper around TextFormat.PrintToString. + /// </summary> + public override String ToString() { + return TextFormat.PrintToString(this); + } + + /// <summary> + /// Serializes the message to a ByteString and returns it. This is + /// just a trivial wrapper around WriteTo(CodedOutputStream). + /// </summary> + /// <returns></returns> + public ByteString ToByteString() { + ByteString.CodedBuilder codedBuilder = new ByteString.CodedBuilder(SerializedSize); + WriteTo(codedBuilder.CodedOutput); + return codedBuilder.Build(); + } + + /// <summary> + /// Serializes the message to a byte array and returns it. This is + /// just a trivial wrapper around WriteTo(CodedOutputStream). + /// </summary> + /// <returns></returns> + public byte[] ToByteArray() { + byte[] data = new byte[SerializedSize]; + CodedOutputStream output = CodedOutputStream.CreateInstance(data); + WriteTo(output); + output.CheckNoSpaceLeft(); + return data; + } + + /// <summary> + /// Serializes the message and writes it to <paramref name="output"/>. This is + /// just a trivial wrapper around WriteTo(CodedOutputStream). + /// </summary> + /// <param name="output"></param> + public void WriteTo(Stream output) { + CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output); + WriteTo(codedOutput); + codedOutput.Flush(); + } + + /// <summary> + /// Serializes the set and writes it to <paramref name="output"/> using + /// the MessageSet wire format. + /// </summary> + public void WriteAsMessageSetTo(CodedOutputStream output) { + foreach (KeyValuePair<int, UnknownField> entry in fields) { + entry.Value.WriteAsMessageSetExtensionTo(entry.Key, output); + } + } + + /// <summary> + /// Gets the number of bytes required to encode this set using the MessageSet + /// wire format. + /// </summary> + public int SerializedSizeAsMessageSet { + get { + int result = 0; + foreach (KeyValuePair<int, UnknownField> entry in fields) { + result += entry.Value.GetSerializedSizeAsMessageSetExtension(entry.Key); + } + return result; + } + } + + /// <summary> + /// Parses an UnknownFieldSet from the given input. + /// </summary> + public static UnknownFieldSet ParseFrom(CodedInputStream input) { + return CreateBuilder().MergeFrom(input).Build(); + } + + /// <summary> + /// Parses an UnknownFieldSet from the given data. + /// </summary> + public static UnknownFieldSet ParseFrom(ByteString data) { + return CreateBuilder().MergeFrom(data).Build(); + } + + /// <summary> + /// Parses an UnknownFieldSet from the given data. + /// </summary> + public static UnknownFieldSet ParseFrom(byte[] data) { + return CreateBuilder().MergeFrom(data).Build(); + } + + /// <summary> + /// Parses an UnknownFieldSet from the given input. + /// </summary> + public static UnknownFieldSet ParseFrom(Stream input) { + return CreateBuilder().MergeFrom(input).Build(); + } + + /// <summary> + /// Builder for UnknownFieldSets. + /// </summary> + public sealed class Builder + { + /// <summary> + /// Mapping from number to field. Note that by using a SortedList we ensure + /// that the fields will be serialized in ascending order. + /// </summary> + private IDictionary<int, UnknownField> fields = new SortedList<int, UnknownField>(); + + // Optimization: We keep around a builder for the last field that was + // modified so that we can efficiently add to it multiple times in a + // row (important when parsing an unknown repeated field). + int lastFieldNumber; + UnknownField.Builder lastField; + + internal Builder() { + } + + /// <summary> + /// Returns a field builder for the specified field number, including any values + /// which already exist. + /// </summary> + private UnknownField.Builder GetFieldBuilder(int number) { + if (lastField != null) { + if (number == lastFieldNumber) { + return lastField; + } + // Note: AddField() will reset lastField and lastFieldNumber. + AddField(lastFieldNumber, lastField.Build()); + } + if (number == 0) { + return null; + } + + lastField = UnknownField.CreateBuilder(); + UnknownField existing; + if (fields.TryGetValue(number, out existing)) { + lastField.MergeFrom(existing); + } + lastFieldNumber = number; + return lastField; + } + + /// <summary> + /// Build the UnknownFieldSet and return it. Once this method has been called, + /// this instance will no longer be usable. Calling any method after this + /// will throw a NullReferenceException. + /// </summary> + public UnknownFieldSet Build() { + GetFieldBuilder(0); // Force lastField to be built. + UnknownFieldSet result = fields.Count == 0 ? DefaultInstance : new UnknownFieldSet(fields); + fields = null; + return result; + } + + /// <summary> + /// Adds a field to the set. If a field with the same number already exists, it + /// is replaced. + /// </summary> + public Builder AddField(int number, UnknownField field) { + if (number == 0) { + throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); + } + if (lastField != null && lastFieldNumber == number) { + // Discard this. + lastField = null; + lastFieldNumber = 0; + } + fields[number] = field; + return this; + } + + /// <summary> + /// Resets the builder to an empty set. + /// </summary> + public Builder Clear() { + fields.Clear(); + lastFieldNumber = 0; + lastField = null; + return this; + } + + /// <summary> + /// Parse an entire message from <paramref name="input"/> and merge + /// its fields into this set. + /// </summary> + public Builder MergeFrom(CodedInputStream input) { + while (true) { + uint tag = input.ReadTag(); + if (tag == 0 || !MergeFieldFrom(tag, input)) { + break; + } + } + return this; + } + + /// <summary> + /// Parse a single field from <paramref name="input"/> and merge it + /// into this set. + /// </summary> + /// <param name="tag">The field's tag number, which was already parsed.</param> + /// <param name="input">The coded input stream containing the field</param> + /// <returns>false if the tag is an "end group" tag, true otherwise</returns> + public bool MergeFieldFrom(uint tag, CodedInputStream input) { + int number = WireFormat.GetTagFieldNumber(tag); + switch (WireFormat.GetTagWireType(tag)) { + case WireFormat.WireType.Varint: + GetFieldBuilder(number).AddVarint(input.ReadUInt64()); + return true; + case WireFormat.WireType.Fixed64: + GetFieldBuilder(number).AddFixed64(input.ReadFixed64()); + return true; + case WireFormat.WireType.LengthDelimited: + GetFieldBuilder(number).AddLengthDelimited(input.ReadBytes()); + return true; + case WireFormat.WireType.StartGroup: { + Builder subBuilder = CreateBuilder(); + input.ReadUnknownGroup(number, subBuilder); + GetFieldBuilder(number).AddGroup(subBuilder.Build()); + return true; + } + case WireFormat.WireType.EndGroup: + return false; + case WireFormat.WireType.Fixed32: + GetFieldBuilder(number).AddFixed32(input.ReadFixed32()); + return true; + default: + throw InvalidProtocolBufferException.InvalidWireType(); + } + } + + /// <summary> + /// Parses <paramref name="input"/> as an UnknownFieldSet and merge it + /// with the set being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream). + /// </summary> + public Builder MergeFrom(Stream input) { + CodedInputStream codedInput = CodedInputStream.CreateInstance(input); + MergeFrom(codedInput); + codedInput.CheckLastTagWas(0); + return this; + } + + /// <summary> + /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it + /// with the set being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream). + /// </summary> + public Builder MergeFrom(ByteString data) { + CodedInputStream input = data.CreateCodedInput(); + MergeFrom(input); + input.CheckLastTagWas(0); + return this; + } + + /// <summary> + /// Parses <paramref name="data"/> as an UnknownFieldSet and merge it + /// with the set being built. This is just a small wrapper around + /// MergeFrom(CodedInputStream). + /// </summary> + public Builder MergeFrom(byte[] data) { + CodedInputStream input = CodedInputStream.CreateInstance(data); + MergeFrom(input); + input.CheckLastTagWas(0); + return this; + } + + /// <summary> + /// Convenience method for merging a new field containing a single varint + /// value. This is used in particular when an unknown enum value is + /// encountered. + /// </summary> + public Builder MergeVarintField(int number, ulong value) { + if (number == 0) { + throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); + } + GetFieldBuilder(number).AddVarint(value); + return this; + } + + /// <summary> + /// Merges the fields from <paramref name="other"/> into this set. + /// If a field number exists in both sets, the values in <paramref name="other"/> + /// will be appended to the values in this set. + /// </summary> + public Builder MergeFrom(UnknownFieldSet other) { + if (other != DefaultInstance) { + foreach(KeyValuePair<int, UnknownField> entry in other.fields) { + MergeField(entry.Key, entry.Value); + } + } + return this; + } + + /// <summary> + /// Checks if the given field number is present in the set. + /// </summary> + public bool HasField(int number) { + if (number == 0) { + throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); + } + return number == lastFieldNumber || fields.ContainsKey(number); + } + + /// <summary> + /// Adds a field to the unknown field set. If a field with the same + /// number already exists, the two are merged. + /// </summary> + public Builder MergeField(int number, UnknownField field) { + if (number == 0) { + throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); + } + if (HasField(number)) { + GetFieldBuilder(number).MergeFrom(field); + } else { + // Optimization: We could call getFieldBuilder(number).mergeFrom(field) + // in this case, but that would create a copy of the Field object. + // We'd rather reuse the one passed to us, so call AddField() instead. + AddField(number, field); + } + return this; + } + + internal void MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder) { + while (true) { + uint tag = input.ReadTag(); + if (tag == 0) { + break; + } + if (!MergeFieldFrom(input, extensionRegistry, builder, tag)) { + // end group tag + break; + } + } + } + + /// <summary> + /// Like <see cref="MergeFrom(CodedInputStream, ExtensionRegistry, IBuilder)" /> + /// but parses a single field. + /// </summary> + /// <param name="input">The input to read the field from</param> + /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param> + /// <param name="builder">Builder to merge field into, if it's a known field</param> + /// <param name="tag">The tag, which should already have been read from the input</param> + /// <returns>true unless the tag is an end-group tag</returns> + internal bool MergeFieldFrom(CodedInputStream input, + ExtensionRegistry extensionRegistry, IBuilder builder, uint tag) { + + if (DescriptorProtoFile.Bootstrapping) { + return MergeFieldFrom(tag, input); + } + + MessageDescriptor type = builder.DescriptorForType; + if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart) { + MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder); + return true; + } + + WireFormat.WireType wireType = WireFormat.GetTagWireType(tag); + int fieldNumber = WireFormat.GetTagFieldNumber(tag); + + FieldDescriptor field; + IMessage defaultFieldInstance = null; + + if (type.IsExtensionNumber(fieldNumber)) { + ExtensionInfo extension = extensionRegistry[type, fieldNumber]; + if (extension == null) { + field = null; + } else { + field = extension.Descriptor; + defaultFieldInstance = extension.DefaultInstance; + } + } else { + field = type.FindFieldByNumber(fieldNumber); + } + + // Unknown field or wrong wire type. Skip. + if (field == null || wireType != WireFormat.GetWireType(field.FieldType)) { + return MergeFieldFrom(tag, input); + } + + object value; + switch (field.FieldType) { + case FieldType.Group: + case FieldType.Message: { + IBuilder subBuilder; + if (defaultFieldInstance != null) { + subBuilder = defaultFieldInstance.WeakCreateBuilderForType(); + } else { + subBuilder = builder.CreateBuilderForField(field); + } + if (!field.IsRepeated) { + subBuilder.WeakMergeFrom((IMessage)builder[field]); + } + if (field.FieldType == FieldType.Group) { + input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry); + } else { + input.ReadMessage(subBuilder, extensionRegistry); + } + value = subBuilder.WeakBuild(); + break; + } + case FieldType.Enum: { + int rawValue = input.ReadEnum(); + value = field.EnumType.FindValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // drop it. + if (value == null) { + MergeVarintField(fieldNumber, (ulong)rawValue); + return true; + } + break; + } + default: + value = input.ReadPrimitiveField(field.FieldType); + break; + } + if (field.IsRepeated) { + builder.WeakAddRepeatedField(field, value); + } else { + builder[field] = value; + } + return true; + } + + /// <summary> + /// Called by MergeFieldFrom to parse a MessageSet extension. + /// </summary> + private void MergeMessageSetExtensionFromCodedStream(CodedInputStream input, + ExtensionRegistry extensionRegistry, IBuilder builder) { + MessageDescriptor type = builder.DescriptorForType; + + // The wire format for MessageSet is: + // message MessageSet { + // repeated group Item = 1 { + // required int32 typeId = 2; + // required bytes message = 3; + // } + // } + // "typeId" is the extension's field number. The extension can only be + // a message type, where "message" contains the encoded bytes of that + // message. + // + // In practice, we will probably never see a MessageSet item in which + // the message appears before the type ID, or where either field does not + // appear exactly once. However, in theory such cases are valid, so we + // should be prepared to accept them. + + int typeId = 0; + ByteString rawBytes = null; // If we encounter "message" before "typeId" + IBuilder subBuilder = null; + FieldDescriptor field = null; + + while (true) { + uint tag = input.ReadTag(); + if (tag == 0) { + break; + } + + if (tag == WireFormat.MessageSetTag.TypeID) { + typeId = input.ReadInt32(); + // Zero is not a valid type ID. + if (typeId != 0) { + ExtensionInfo extension = extensionRegistry[type, typeId]; + if (extension != null) { + field = extension.Descriptor; + subBuilder = extension.DefaultInstance.WeakCreateBuilderForType(); + IMessage originalMessage = (IMessage)builder[field]; + if (originalMessage != null) { + subBuilder.WeakMergeFrom(originalMessage); + } + if (rawBytes != null) { + // We already encountered the message. Parse it now. + // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes. + // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry? + subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput()); + rawBytes = null; + } + } else { + // Unknown extension number. If we already saw data, put it + // in rawBytes. + if (rawBytes != null) { + MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build()); + rawBytes = null; + } + } + } + } else if (tag == WireFormat.MessageSetTag.Message) { + if (typeId == 0) { + // We haven't seen a type ID yet, so we have to store the raw bytes for now. + rawBytes = input.ReadBytes(); + } else if (subBuilder == null) { + // We don't know how to parse this. Ignore it. + MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(input.ReadBytes()).Build()); + } else { + // We already know the type, so we can parse directly from the input + // with no copying. Hooray! + input.ReadMessage(subBuilder, extensionRegistry); + } + } else { + // Unknown tag. Skip it. + if (!input.SkipField(tag)) { + break; // end of group + } + } + } + + input.CheckLastTagWas(WireFormat.MessageSetTag.ItemEnd); + + if (subBuilder != null) { + builder[field] = subBuilder.WeakBuild(); + } + } + } + } +} diff --git a/src/ProtocolBuffers/WireFormat.cs b/src/ProtocolBuffers/WireFormat.cs new file mode 100644 index 00000000..0ea93322 --- /dev/null +++ b/src/ProtocolBuffers/WireFormat.cs @@ -0,0 +1,122 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Reflection; +using Google.ProtocolBuffers.Descriptors; +using System.Collections.Generic; +using Google.ProtocolBuffers.Collections; +namespace Google.ProtocolBuffers { + + /// <summary> + /// This class is used internally by the Protocol Buffer Library and generated + /// message implementations. It is public only for the sake of those generated + /// messages. Others should not use this class directly. + /// <para> + /// This class contains constants and helper functions useful for dealing with + /// the Protocol Buffer wire format. + /// </para> + /// </summary> + public static class WireFormat { + public enum WireType : uint { + Varint = 0, + Fixed64 = 1, + LengthDelimited = 2, + StartGroup = 3, + EndGroup = 4, + Fixed32 = 5 + } + + internal static class MessageSetField { + internal const int Item = 1; + internal const int TypeID = 2; + internal const int Message = 3; + } + + internal static class MessageSetTag { + internal static readonly uint ItemStart = MakeTag(MessageSetField.Item, WireType.StartGroup); + internal static readonly uint ItemEnd = MakeTag(MessageSetField.Item, WireType.EndGroup); + internal static readonly uint TypeID = MakeTag(MessageSetField.TypeID, WireType.Varint); + internal static readonly uint Message = MakeTag(MessageSetField.Message, WireType.LengthDelimited); + } + + private const int TagTypeBits = 3; + private const uint TagTypeMask = (1 << TagTypeBits) - 1; + + /// <summary> + /// Given a tag value, determines the wire type (lower 3 bits). + /// </summary> + public static WireType GetTagWireType(uint tag) { + return (WireType) (tag & TagTypeMask); + } + + /// <summary> + /// Given a tag value, determines the field number (the upper 29 bits). + /// </summary> + public static int GetTagFieldNumber(uint tag) { + return (int) tag >> TagTypeBits; + } + + /// <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) { + return (uint) (fieldNumber << TagTypeBits) | (uint) wireType; + } + + /// <summary> + /// Converts a field type to its wire type. Done with a switch for the sake + /// of speed - this is significantly faster than a dictionary lookup. + /// </summary> + public static WireType GetWireType(FieldType fieldType) { + switch (fieldType) { + case FieldType.Double: + return WireType.Fixed64; + case FieldType.Float: + return WireType.Fixed32; + case FieldType.Int64: + case FieldType.UInt64: + case FieldType.Int32: + return WireType.Varint; + case FieldType.Fixed64: + return WireType.Fixed64; + case FieldType.Fixed32: + return WireType.Fixed32; + case FieldType.Bool: + return WireType.Varint; + case FieldType.String: + return WireType.LengthDelimited; + case FieldType.Group: + return WireType.StartGroup; + case FieldType.Message: + case FieldType.Bytes: + return WireType.LengthDelimited; + case FieldType.UInt32: + return WireType.Varint; + case FieldType.SFixed32: + return WireType.Fixed32; + case FieldType.SFixed64: + return WireType.Fixed64; + case FieldType.SInt32: + case FieldType.SInt64: + case FieldType.Enum: + return WireType.Varint; + default: + throw new ArgumentOutOfRangeException("No such field type"); + } + } + } +} |