Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.4/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/0.9.1/ProtobufCS/src/ProtocolBuffers/ExtendableMessage.cs

Last change on this file was 3857, checked in by abeham, 14 years ago

#866

  • Added protobuf-csharp-port project source to ExtLibs
File size: 8.1 KB
Line 
1#region Copyright notice and license
2// Protocol Buffers - Google's data interchange format
3// Copyright 2008 Google Inc.  All rights reserved.
4// http://github.com/jskeet/dotnet-protobufs/
5// Original C++/Java/Python code:
6// http://code.google.com/p/protobuf/
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
11//
12//     * Redistributions of source code must retain the above copyright
13// notice, this list of conditions and the following disclaimer.
14//     * Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following disclaimer
16// in the documentation and/or other materials provided with the
17// distribution.
18//     * Neither the name of Google Inc. nor the names of its
19// contributors may be used to endorse or promote products derived from
20// this software without specific prior written permission.
21//
22// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33#endregion
34
35using System;
36using System.Collections.Generic;
37using Google.ProtocolBuffers.Collections;
38using Google.ProtocolBuffers.Descriptors;
39
40namespace Google.ProtocolBuffers {
41  public abstract class ExtendableMessage<TMessage, TBuilder> : GeneratedMessage<TMessage, TBuilder>
42    where TMessage : GeneratedMessage<TMessage, TBuilder>
43    where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
44
45    protected ExtendableMessage() {}
46    private readonly FieldSet extensions = FieldSet.CreateInstance();
47
48    /// <summary>
49    /// Access for the builder.
50    /// </summary>
51    internal FieldSet Extensions {
52      get { return extensions; }
53    }
54
55    /// <summary>
56    /// Checks if a singular extension is present.
57    /// </summary>
58    public bool HasExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
59      return extensions.HasField(extension.Descriptor);
60    }
61
62    /// <summary>
63    /// Returns the number of elements in a repeated extension.
64    /// </summary>
65    public int GetExtensionCount<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension) {
66      return extensions.GetRepeatedFieldCount(extension.Descriptor);
67    }
68
69    /// <summary>
70    /// Returns the value of an extension.
71    /// </summary>
72    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
73      object value = extensions[extension.Descriptor];
74      if (value == null) {
75        return (TExtension) extension.MessageDefaultInstance;
76      } else {
77        return (TExtension) extension.FromReflectionType(value);
78      }
79    }
80
81    /// <summary>
82    /// Returns one element of a repeated extension.
83    /// </summary>
84    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index) {
85      return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
86    }
87
88    /// <summary>
89    /// Called to check if all extensions are initialized.
90    /// </summary>
91    protected bool ExtensionsAreInitialized {
92      get { return extensions.IsInitialized; }     
93    }
94
95    public override bool IsInitialized {
96      get {
97        return base.IsInitialized && ExtensionsAreInitialized;
98      }
99    }
100
101    #region Reflection
102    public override IDictionary<FieldDescriptor, object> AllFields {
103      get {
104        IDictionary<FieldDescriptor, object> result = GetMutableFieldMap();
105        foreach(KeyValuePair<FieldDescriptor, object> entry in extensions.AllFields) {
106          result[entry.Key] = entry.Value;
107        }
108        return Dictionaries.AsReadOnly(result);
109      }
110    }
111
112    public override bool HasField(FieldDescriptor field) {
113      if (field.IsExtension) {
114        VerifyContainingType(field);
115        return extensions.HasField(field);
116      } else {
117        return base.HasField(field);
118      }
119    }
120
121    public override object this[FieldDescriptor field] {
122      get {
123        if (field.IsExtension) {
124          VerifyContainingType(field);
125          object value = extensions[field];
126          if (value == null) {
127            // Lacking an ExtensionRegistry, we have no way to determine the
128            // extension's real type, so we return a DynamicMessage.
129            // TODO(jonskeet): Work out what this means
130            return DynamicMessage.GetDefaultInstance(field.MessageType);
131          } else {
132            return value;
133          }
134        } else {
135          return base[field];
136        }
137      }
138    }
139
140    public override int GetRepeatedFieldCount(FieldDescriptor field) {
141      if (field.IsExtension) {
142        VerifyContainingType(field);
143        return extensions.GetRepeatedFieldCount(field);
144      } else {
145        return base.GetRepeatedFieldCount(field);
146      }
147    }
148
149    public override object this[FieldDescriptor field, int index] {
150      get {
151        if (field.IsExtension) {
152          VerifyContainingType(field);
153          return extensions[field, index];
154        } else {
155          return base[field, index];
156        }
157      }
158    }
159 
160    internal void VerifyContainingType(FieldDescriptor field) {
161      if (field.ContainingType != DescriptorForType) {
162        throw new ArgumentException("FieldDescriptor does not match message type.");
163      }
164    }
165    #endregion
166
167    /// <summary>
168    /// Used by subclasses to serialize extensions. Extension ranges may be
169    /// interleaves with field numbers, but we must write them in canonical
170    /// (sorted by field number) order. This class helps us to write individual
171    /// ranges of extensions at once.
172    ///
173    /// TODO(jonskeet): See if we can improve this in terms of readability.
174    /// </summary>
175    protected class ExtensionWriter {
176      readonly IEnumerator<KeyValuePair<FieldDescriptor, object>> iterator;
177      readonly FieldSet extensions;
178      KeyValuePair<FieldDescriptor, object>? next = null;
179
180      internal ExtensionWriter(ExtendableMessage<TMessage, TBuilder> message) {
181        extensions = message.extensions;
182        iterator = message.extensions.GetEnumerator();
183        if (iterator.MoveNext()) {
184          next = iterator.Current;
185        }
186      }
187
188      public void WriteUntil(int end, CodedOutputStream output) {
189        while (next != null && next.Value.Key.FieldNumber < end) {
190          extensions.WriteField(next.Value.Key, next.Value.Value, output);
191          if (iterator.MoveNext()) {
192            next = iterator.Current;
193          } else {
194            next = null;
195          }
196        }
197      }
198    }
199
200    protected ExtensionWriter CreateExtensionWriter(ExtendableMessage<TMessage, TBuilder> message) {
201      return new ExtensionWriter(message);
202    }
203
204    /// <summary>
205    /// Called by subclasses to compute the size of extensions.
206    /// </summary>
207    protected int ExtensionsSerializedSize {
208      get { return extensions.SerializedSize; }
209    }
210
211    internal void VerifyExtensionContainingType<TExtension>(GeneratedExtensionBase<TExtension> extension) {
212      if (extension.Descriptor.ContainingType != DescriptorForType) {
213        // This can only happen if someone uses unchecked operations.
214        throw new ArgumentException("Extension is for type \"" + extension.Descriptor.ContainingType.FullName
215          + "\" which does not match message type \"" + DescriptorForType.FullName + "\".");
216      }
217    }
218  }
219}
Note: See TracBrowser for help on using the repository browser.