using System; using System.Collections.Generic; using System.IO; namespace Google.ProtocolBuffers { /// /// 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. /// public interface IBuilder { IBuilder MergeFrom(CodedInputStream codedInputStream, ExtensionRegistry extensionRegistry); /// /// Returns true iff all required fields in the message and all /// embedded messages are set. /// bool Initialized { get; } /// /// 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. /// IDictionary AllFields { get; } /// /// Allows getting and setting of a field. /// /// /// /// object this[Descriptors.FieldDescriptor field] { get; set; } /// /// Get the message's type's descriptor. /// /// Descriptors.Descriptor DescriptorForType { get; } /// /// /// /// /// int GetRepeatedFieldCount(Descriptors.FieldDescriptor field); /// /// Allows getting and setting of a repeated field value. /// /// object this[Descriptors.FieldDescriptor field, int index] { get; set; } /// /// /// bool HasField(Descriptors.FieldDescriptor field); } /// /// Interface implemented by Protocol Message builders. /// TODO(jonskeet): Consider "SetXXX" methods returning the builder, as well as the properties. /// /// Type of message public interface IBuilder : IBuilder where T : IMessage { /// /// Resets all fields to their default values. /// IBuilder Clear(); /// /// 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 , /// then 's value overwrites the value in this message. /// For singular message fields, if the field is set in , /// it is merged into the corresponding sub-message of this message using the same /// merging rules. /// For repeated fields, the elements in are concatenated /// with the elements in this message. /// /// /// IBuilder MergeFrom(IMessage other); /// /// 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. /// /// the message /// is missing one or more required fields; use BuildPartial to bypass /// this check IMessage Build(); /// /// Like Build(), but does not throw an exception if the message is missing /// required fields. Instead, a partial message is returned. /// /// IMessage BuildPartial(); /// /// Clones this builder. /// TODO(jonskeet): Explain depth of clone. /// IBuilder Clone(); /// /// Parses a message of this type from the input and merges it with this /// message, as if using MergeFrom(IMessage<T>). /// /// /// 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: /// /// Call Initialized to verify to verify that all required fields are /// set before building. /// 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. /// /// IBuilder MergeFrom(CodedInputStream input); /// /// Like MergeFrom(CodedInputStream), but also parses extensions. /// The extensions that you want to be able to parse must be registered /// in . Extensions not in the registry /// will be treated as unknown fields. /// new IBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry); /// /// Get's the message's type's default instance. /// /// IMessage DefaultInstanceForType { get; } /// /// 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. /// /// /// /// IBuilder NewBuilderForField(Descriptors.FieldDescriptor field) where TField : IMessage; /// /// Clears the field. This is exactly equivalent to calling the generated /// Clear method corresponding to the field. /// /// /// IBuilder ClearField(Descriptors.FieldDescriptor field); /// /// Appends the given value as a new element for the specified repeated field. /// /// 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 /// IBuilder AddRepeatedField(Descriptors.FieldDescriptor field, object value); /// /// /// UnknownFieldSet UnknownFields { get; set; } /// /// Merge some unknown fields into the set for this message. /// IBuilder MergeUnknownFields(UnknownFieldSet unknownFields); #region Convenience methods // TODO(jonskeet): Implement these as extension methods? /// /// Parse as a message of this type and merge /// it with the message being built. This is just a small wrapper around /// MergeFrom(CodedInputStream). /// IBuilder MergeFrom(ByteString data); /// /// Parse as a message of this type and merge /// it with the message being built. This is just a small wrapper around /// MergeFrom(CodedInputStream, ExtensionRegistry). /// IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry); /// /// Parse as a message of this type and merge /// it with the message being built. This is just a small wrapper around /// MergeFrom(CodedInputStream). /// IBuilder MergeFrom(byte[] data); /// /// Parse as a message of this type and merge /// it with the message being built. This is just a small wrapper around /// MergeFrom(CodedInputStream, ExtensionRegistry). /// IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry); /// /// Parse 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. /// IBuilder MergeFrom(Stream input); /// /// Parse as a message of this type and merge /// it with the message being built. This is just a small wrapper around /// MergeFrom(CodedInputStream, ExtensionRegistry). /// IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry); #endregion } }