Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RemoveBackwardsCompatibility/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/2.4.1/ProtobufCS/src/ProtocolBuffers/AbstractMessage.cs

Last change on this file was 8295, checked in by abeham, 12 years ago

#1897:

  • Removed protocol buffers 0.9.1
  • Added protocol buffers 2.4.1
  • Updated proto processing command
File size: 11.5 KB
Line 
1#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc.  All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13//     * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//     * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19//     * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System.Collections;
38using System.Collections.Generic;
39using System.IO;
40using System.Text;
41using Google.ProtocolBuffers.Collections;
42using Google.ProtocolBuffers.Descriptors;
43
44namespace Google.ProtocolBuffers
45{
46    /// <summary>
47    /// Implementation of the non-generic IMessage interface as far as possible.
48    /// </summary>
49    public abstract partial class AbstractMessage<TMessage, TBuilder> : AbstractMessageLite<TMessage, TBuilder>,
50                                                                IMessage<TMessage, TBuilder>
51        where TMessage : AbstractMessage<TMessage, TBuilder>
52        where TBuilder : AbstractBuilder<TMessage, TBuilder>
53    {
54        /// <summary>
55        /// The serialized size if it's already been computed, or null
56        /// if we haven't computed it yet.
57        /// </summary>
58        private int? memoizedSize = null;
59
60        #region Unimplemented members of IMessage
61
62        public abstract MessageDescriptor DescriptorForType { get; }
63        public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
64        public abstract bool HasField(FieldDescriptor field);
65        public abstract object this[FieldDescriptor field] { get; }
66        public abstract int GetRepeatedFieldCount(FieldDescriptor field);
67        public abstract object this[FieldDescriptor field, int index] { get; }
68        public abstract UnknownFieldSet UnknownFields { get; }
69
70        #endregion
71
72        /// <summary>
73        /// Returns true iff all required fields in the message and all embedded
74        /// messages are set.
75        /// </summary>
76        public override bool IsInitialized
77        {
78            get
79            {
80                // Check that all required fields are present.
81                foreach (FieldDescriptor field in DescriptorForType.Fields)
82                {
83                    if (field.IsRequired && !HasField(field))
84                    {
85                        return false;
86                    }
87                }
88
89                // Check that embedded messages are initialized.
90                foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields)
91                {
92                    FieldDescriptor field = entry.Key;
93                    if (field.MappedType == MappedType.Message)
94                    {
95                        if (field.IsRepeated)
96                        {
97                            // We know it's an IList<T>, but not the exact type - so
98                            // IEnumerable is the best we can do. (C# generics aren't covariant yet.)
99                            foreach (IMessageLite element in (IEnumerable) entry.Value)
100                            {
101                                if (!element.IsInitialized)
102                                {
103                                    return false;
104                                }
105                            }
106                        }
107                        else
108                        {
109                            if (!((IMessageLite) entry.Value).IsInitialized)
110                            {
111                                return false;
112                            }
113                        }
114                    }
115                }
116                return true;
117            }
118        }
119
120        public override sealed string ToString()
121        {
122            return TextFormat.PrintToString(this);
123        }
124
125        public override sealed void PrintTo(TextWriter writer)
126        {
127            TextFormat.Print(this, writer);
128        }
129
130        /// <summary>
131        /// Serializes the message and writes it to the given output stream.
132        /// This does not flush or close the stream.
133        /// </summary>
134        /// <remarks>
135        /// Protocol Buffers are not self-delimiting. Therefore, if you write
136        /// any more data to the stream after the message, you must somehow ensure
137        /// that the parser on the receiving end does not interpret this as being
138        /// part of the protocol message. One way of doing this is by writing the size
139        /// of the message before the data, then making sure you limit the input to
140        /// that size when receiving the data. Alternatively, use WriteDelimitedTo(Stream).
141        /// </remarks>
142        public override void WriteTo(ICodedOutputStream output)
143        {
144            foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields)
145            {
146                FieldDescriptor field = entry.Key;
147                if (field.IsRepeated)
148                {
149                    // We know it's an IList<T>, but not the exact type - so
150                    // IEnumerable is the best we can do. (C# generics aren't covariant yet.)
151                    IEnumerable valueList = (IEnumerable) entry.Value;
152                    if (field.IsPacked)
153                    {
154                        output.WritePackedArray(field.FieldType, field.FieldNumber, field.Name, valueList);
155                    }
156                    else
157                    {
158                        output.WriteArray(field.FieldType, field.FieldNumber, field.Name, valueList);
159                    }
160                }
161                else
162                {
163                    output.WriteField(field.FieldType, field.FieldNumber, field.Name, entry.Value);
164                }
165            }
166
167            UnknownFieldSet unknownFields = UnknownFields;
168            if (DescriptorForType.Options.MessageSetWireFormat)
169            {
170                unknownFields.WriteAsMessageSetTo(output);
171            }
172            else
173            {
174                unknownFields.WriteTo(output);
175            }
176        }
177
178        /// <summary>
179        /// Returns the number of bytes required to encode this message.
180        /// The result is only computed on the first call and memoized after that.
181        /// </summary>
182        public override int SerializedSize
183        {
184            get
185            {
186                if (memoizedSize != null)
187                {
188                    return memoizedSize.Value;
189                }
190
191                int size = 0;
192                foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields)
193                {
194                    FieldDescriptor field = entry.Key;
195                    if (field.IsRepeated)
196                    {
197                        IEnumerable valueList = (IEnumerable) entry.Value;
198                        if (field.IsPacked)
199                        {
200                            int dataSize = 0;
201                            foreach (object element in valueList)
202                            {
203                                dataSize += CodedOutputStream.ComputeFieldSizeNoTag(field.FieldType, element);
204                            }
205                            size += dataSize;
206                            size += CodedOutputStream.ComputeTagSize(field.FieldNumber);
207                            size += CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
208                        }
209                        else
210                        {
211                            foreach (object element in valueList)
212                            {
213                                size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, element);
214                            }
215                        }
216                    }
217                    else
218                    {
219                        size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, entry.Value);
220                    }
221                }
222
223                UnknownFieldSet unknownFields = UnknownFields;
224                if (DescriptorForType.Options.MessageSetWireFormat)
225                {
226                    size += unknownFields.SerializedSizeAsMessageSet;
227                }
228                else
229                {
230                    size += unknownFields.SerializedSize;
231                }
232
233                memoizedSize = size;
234                return size;
235            }
236        }
237
238        /// <summary>
239        /// Compares the specified object with this message for equality.
240        /// Returns true iff the given object is a message of the same type
241        /// (as defined by DescriptorForType) and has identical values
242        /// for all its fields.
243        /// </summary>
244        public override bool Equals(object other)
245        {
246            if (other == this)
247            {
248                return true;
249            }
250            IMessage otherMessage = other as IMessage;
251            if (otherMessage == null || otherMessage.DescriptorForType != DescriptorForType)
252            {
253                return false;
254            }
255            return Dictionaries.Equals(AllFields, otherMessage.AllFields) &&
256                   UnknownFields.Equals(otherMessage.UnknownFields);
257        }
258
259        /// <summary>
260        /// Returns the hash code value for this message.
261        /// TODO(jonskeet): Specify the hash algorithm, but better than the Java one!
262        /// </summary>
263        public override int GetHashCode()
264        {
265            int hash = 41;
266            hash = (19*hash) + DescriptorForType.GetHashCode();
267            hash = (53*hash) + Dictionaries.GetHashCode(AllFields);
268            hash = (29*hash) + UnknownFields.GetHashCode();
269            return hash;
270        }
271
272        #region Explicit Members
273
274        IBuilder IMessage.WeakCreateBuilderForType()
275        {
276            return CreateBuilderForType();
277        }
278
279        IBuilder IMessage.WeakToBuilder()
280        {
281            return ToBuilder();
282        }
283
284        IMessage IMessage.WeakDefaultInstanceForType
285        {
286            get { return DefaultInstanceForType; }
287        }
288
289        #endregion
290    }
291}
Note: See TracBrowser for help on using the repository browser.