blob: 4100dedd3feeaeb62aa76e7378c7705830e6052b [file] [log] [blame]
Jon Skeet68036862008-10-22 13:30:34 +01001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.
3// http://code.google.com/p/protobuf/
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16using System;
17using System.Collections.Generic;
18using System.IO;
19using Google.ProtocolBuffers.Descriptors;
20
21namespace Google.ProtocolBuffers {
22
23 /// <summary>
24 /// Non-generic interface for all members whose signatures don't require knowledge of
25 /// the type being built. The generic interface extends this one. Some methods return
26 /// either an IBuilder or an IMessage; in these cases the generic interface redeclares
27 /// the same method with a type-specific signature. Implementations are encouraged to
28 /// use explicit interface implemenation for the non-generic form. This mirrors
29 /// how IEnumerable and IEnumerable&lt;T&gt; work.
30 /// </summary>
31 public interface IBuilder {
32 /// <summary>
33 /// Returns true iff all required fields in the message and all
34 /// embedded messages are set.
35 /// </summary>
36 bool IsInitialized { get; }
37
38 /// <summary>
39 /// Only present in the nongeneric interface - useful for tests, but
40 /// not as much in real life.
41 /// </summary>
42 IBuilder SetField(FieldDescriptor field, object value);
43
44 /// <summary>
45 /// Only present in the nongeneric interface - useful for tests, but
46 /// not as much in real life.
47 /// </summary>
48 IBuilder SetRepeatedField(FieldDescriptor field, int index, object value);
49
50 /// <summary>
51 /// Behaves like the equivalent property in IMessage&lt;T&gt;.
52 /// The returned map may or may not reflect future changes to the builder.
53 /// Either way, the returned map is unmodifiable.
54 /// </summary>
55 IDictionary<FieldDescriptor, object> AllFields { get; }
56
57 /// <summary>
58 /// Allows getting and setting of a field.
59 /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor)"/>
60 /// </summary>
61 /// <param name="field"></param>
62 /// <returns></returns>
63 object this[FieldDescriptor field] { get; set; }
64
65 /// <summary>
66 /// Get the message's type descriptor.
67 /// <see cref="IMessage{TMessage, TBuilder}.DescriptorForType"/>
68 /// </summary>
69 MessageDescriptor DescriptorForType { get; }
70
71 /// <summary>
72 /// <see cref="IMessage{TMessage, TBuilder}.GetRepeatedFieldCount"/>
73 /// </summary>
74 /// <param name="field"></param>
75 /// <returns></returns>
76 int GetRepeatedFieldCount(FieldDescriptor field);
77
78 /// <summary>
79 /// Allows getting and setting of a repeated field value.
80 /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor, int)"/>
81 /// </summary>
82 object this[FieldDescriptor field, int index] { get; set; }
83
84 /// <summary>
85 /// <see cref="IMessage{TMessage, TBuilder}.HasField"/>
86 /// </summary>
87 bool HasField(FieldDescriptor field);
88
89 /// <summary>
90 /// <see cref="IMessage{TMessage, TBuilder}.UnknownFields"/>
91 /// </summary>
92 UnknownFieldSet UnknownFields { get; set; }
93
94 /// <summary>
95 /// Create a builder for messages of the appropriate type for the given field.
96 /// Messages built with this can then be passed to the various mutation properties
97 /// and methods.
98 /// </summary>
99 IBuilder CreateBuilderForField(FieldDescriptor field);
100
101 #region Methods which are like those of the generic form, but without any knowledge of the type parameters
102 IBuilder WeakAddRepeatedField(FieldDescriptor field, object value);
103 IBuilder WeakClear();
104 IBuilder WeakClearField(FieldDescriptor field);
105 IBuilder WeakMergeFrom(IMessage message);
106 IBuilder WeakMergeFrom(ByteString data);
107 IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry);
108 IBuilder WeakMergeFrom(CodedInputStream input);
109 IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
110 IMessage WeakBuild();
111 IMessage WeakBuildPartial();
112 IBuilder WeakClone();
113 IMessage WeakDefaultInstanceForType { get; }
114 #endregion
115 }
116
117 /// <summary>
118 /// Interface implemented by Protocol Message builders.
119 /// TODO(jonskeet): Consider "SetXXX" methods returning the builder, as well as the properties.
120 /// </summary>
121 /// <typeparam name="TMessage">Type of message</typeparam>
122 /// <typeparam name="TBuilder">Type of builder</typeparam>
123 public interface IBuilder<TMessage, TBuilder> : IBuilder
124 where TMessage : IMessage<TMessage, TBuilder>
125 where TBuilder : IBuilder<TMessage, TBuilder> {
126
127 TBuilder SetUnknownFields(UnknownFieldSet unknownFields);
128
129 /// <summary>
130 /// Resets all fields to their default values.
131 /// </summary>
132 TBuilder Clear();
133
134 /// <summary>
135 /// Merge the specified other message into the message being
136 /// built. Merging occurs as follows. For each field:
137 /// For singular primitive fields, if the field is set in <paramref name="other"/>,
138 /// then <paramref name="other"/>'s value overwrites the value in this message.
139 /// For singular message fields, if the field is set in <paramref name="other"/>,
140 /// it is merged into the corresponding sub-message of this message using the same
141 /// merging rules.
142 /// For repeated fields, the elements in <paramref name="other"/> are concatenated
143 /// with the elements in this message.
144 /// </summary>
145 /// <param name="other"></param>
146 /// <returns></returns>
147 TBuilder MergeFrom(TMessage other);
148
149 /// <summary>
150 /// Merge the specified other message which may be a different implementation of
151 /// the same message descriptor.
152 /// </summary>
153 TBuilder MergeFrom(IMessage other);
154
155 /// <summary>
156 /// Constructs the final message. Once this is called, this Builder instance
157 /// is no longer valid, and calling any other method may throw a
158 /// NullReferenceException. If you need to continue working with the builder
159 /// after calling Build, call Clone first.
160 /// </summary>
161 /// <exception cref="UninitializedMessageException">the message
162 /// is missing one or more required fields; use BuildPartial to bypass
163 /// this check</exception>
164 TMessage Build();
165
166 /// <summary>
167 /// Like Build(), but does not throw an exception if the message is missing
168 /// required fields. Instead, a partial message is returned.
169 /// </summary>
170 TMessage BuildPartial();
171
172 /// <summary>
173 /// Clones this builder.
174 /// TODO(jonskeet): Explain depth of clone.
175 /// </summary>
176 TBuilder Clone();
177
178 /// <summary>
179 /// Parses a message of this type from the input and merges it with this
180 /// message, as if using MergeFrom(IMessage&lt;T&gt;).
181 /// </summary>
182 /// <remarks>
183 /// Warning: This does not verify that all required fields are present
184 /// in the input message. If you call Build() without setting all
185 /// required fields, it will throw an UninitializedMessageException.
186 /// There are a few good ways to deal with this:
187 /// <list>
188 /// <item>Call IsInitialized to verify to verify that all required fields are
189 /// set before building.</item>
190 /// <item>Parse the message separately using one of the static ParseFrom
191 /// methods, then use MergeFrom(IMessage&lt;T&gt;) to merge it with
192 /// this one. ParseFrom will throw an InvalidProtocolBufferException
193 /// (an IOException) if some required fields are missing.
194 /// Use BuildPartial to build, which ignores missing required fields.
195 /// </list>
196 /// </remarks>
197 TBuilder MergeFrom(CodedInputStream input);
198
199 /// <summary>
200 /// Like MergeFrom(CodedInputStream), but also parses extensions.
201 /// The extensions that you want to be able to parse must be registered
202 /// in <paramref name="extensionRegistry"/>. Extensions not in the registry
203 /// will be treated as unknown fields.
204 /// </summary>
205 TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
206
207 /// <summary>
208 /// Get's the message's type's default instance.
209 /// <see cref="IMessage{TMessage}.DefaultInstanceForType" />
210 /// </summary>
211 TMessage DefaultInstanceForType { get; }
212
213 /// <summary>
214 /// Clears the field. This is exactly equivalent to calling the generated
215 /// Clear method corresponding to the field.
216 /// </summary>
217 /// <param name="field"></param>
218 /// <returns></returns>
219 TBuilder ClearField(FieldDescriptor field);
220
221 /// <summary>
222 /// Appends the given value as a new element for the specified repeated field.
223 /// </summary>
224 /// <exception cref="ArgumentException">the field is not a repeated field,
225 /// the field does not belong to this builder's type, or the value is
226 /// of the incorrect type
227 /// </exception>
228 TBuilder AddRepeatedField(FieldDescriptor field, object value);
229
230 /// <summary>
231 /// Merge some unknown fields into the set for this message.
232 /// </summary>
233 TBuilder MergeUnknownFields(UnknownFieldSet unknownFields);
234
235 #region Convenience methods
236 /// <summary>
237 /// Parse <paramref name="data"/> as a message of this type and merge
238 /// it with the message being built. This is just a small wrapper around
239 /// MergeFrom(CodedInputStream).
240 /// </summary>
241 TBuilder MergeFrom(ByteString data);
242
243 /// <summary>
244 /// Parse <paramref name="data"/> as a message of this type and merge
245 /// it with the message being built. This is just a small wrapper around
246 /// MergeFrom(CodedInputStream, ExtensionRegistry).
247 /// </summary>
248 TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
249
250 /// <summary>
251 /// Parse <paramref name="data"/> as a message of this type and merge
252 /// it with the message being built. This is just a small wrapper around
253 /// MergeFrom(CodedInputStream).
254 /// </summary>
255 TBuilder MergeFrom(byte[] data);
256
257 /// <summary>
258 /// Parse <paramref name="data"/> as a message of this type and merge
259 /// it with the message being built. This is just a small wrapper around
260 /// MergeFrom(CodedInputStream, ExtensionRegistry).
261 /// </summary>
262 TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
263
264 /// <summary>
265 /// Parse <paramref name="input"/> as a message of this type and merge
266 /// it with the message being built. This is just a small wrapper around
267 /// MergeFrom(CodedInputStream). Note that this method always reads
268 /// the entire input (unless it throws an exception). If you want it to
269 /// stop earlier, you will need to wrap the input in a wrapper
270 /// stream which limits reading. Despite usually reading the entire
271 /// stream, this method never closes the stream.
272 /// </summary>
273 TBuilder MergeFrom(Stream input);
274
275 /// <summary>
276 /// Parse <paramref name="input"/> as a message of this type and merge
277 /// it with the message being built. This is just a small wrapper around
278 /// MergeFrom(CodedInputStream, ExtensionRegistry).
279 /// </summary>
280 TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
281 #endregion
282 }
283}