blob: 33969f4bf3775968aadef2812e55552b26c8bd6c [file] [log] [blame]
csharptest980ba8d2010-11-07 16:30:39 -06001#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;
csharptest80824a52010-11-07 17:25:47 -060036using System.Collections;
csharptest980ba8d2010-11-07 16:30:39 -060037using System.Collections.Generic;
38using Google.ProtocolBuffers.Collections;
csharptest804b6d82010-11-07 10:49:33 -060039using Google.ProtocolBuffers.Descriptors;
csharptestd9c59e62010-11-04 19:36:28 -050040
41namespace Google.ProtocolBuffers {
42
43 public interface IGeneratedExtensionLite {
44 int Number { get; }
45 object ContainingType { get; }
46 IMessageLite MessageDefaultInstance { get; }
csharptest7d396f92010-11-08 20:06:46 -060047 IFieldDescriptorLite Descriptor { get; }
csharptestd9c59e62010-11-04 19:36:28 -050048 }
csharptest804b6d82010-11-07 10:49:33 -060049
csharptest980ba8d2010-11-07 16:30:39 -060050 public class ExtensionDescriptorLite : IFieldDescriptorLite {
csharptest272cb8a2010-11-09 20:49:12 -060051 private readonly string fullName;
csharptest980ba8d2010-11-07 16:30:39 -060052 private readonly IEnumLiteMap enumTypeMap;
csharptest804b6d82010-11-07 10:49:33 -060053 private readonly int number;
54 private readonly FieldType type;
55 private readonly bool isRepeated;
56 private readonly bool isPacked;
csharptest980ba8d2010-11-07 16:30:39 -060057 private readonly MappedType mapType;
58 private readonly object defaultValue;
csharptest804b6d82010-11-07 10:49:33 -060059
csharptest272cb8a2010-11-09 20:49:12 -060060 public ExtensionDescriptorLite(string fullName, IEnumLiteMap enumTypeMap, int number, FieldType type, object defaultValue, bool isRepeated, bool isPacked) {
61 this.fullName = fullName;
csharptest804b6d82010-11-07 10:49:33 -060062 this.enumTypeMap = enumTypeMap;
63 this.number = number;
64 this.type = type;
csharptest7d396f92010-11-08 20:06:46 -060065 this.mapType = FieldMappingAttribute.MappedTypeFromFieldType(type);
csharptest804b6d82010-11-07 10:49:33 -060066 this.isRepeated = isRepeated;
67 this.isPacked = isPacked;
csharptest980ba8d2010-11-07 16:30:39 -060068 this.defaultValue = defaultValue;
csharptest804b6d82010-11-07 10:49:33 -060069 }
70
csharptest272cb8a2010-11-09 20:49:12 -060071 public string FullName { get { return fullName; } }
72
csharptest980ba8d2010-11-07 16:30:39 -060073 public bool IsRepeated {
74 get { return isRepeated; }
75 }
76
77 public bool IsRequired {
78 get { return false; }
79 }
80
81 public bool IsPacked {
82 get { return isPacked; }
83 }
84
85 public bool IsExtension {
86 get { return true; }
87 }
88
csharpteste4954772010-11-09 14:47:27 -060089 /// <summary>
90 /// This is not supported and assertions are made to ensure this does not exist on extensions of Lite types
91 /// </summary>
csharptest980ba8d2010-11-07 16:30:39 -060092 public bool MessageSetWireFormat {
csharptest7d396f92010-11-08 20:06:46 -060093 get { return false; }
csharptest980ba8d2010-11-07 16:30:39 -060094 }
95
96 public int FieldNumber {
csharptest804b6d82010-11-07 10:49:33 -060097 get { return number; }
98 }
csharptest980ba8d2010-11-07 16:30:39 -060099
100 public IEnumLiteMap EnumType {
101 get { return enumTypeMap; }
102 }
103
104 public FieldType FieldType {
105 get { return type; }
106 }
107
108 public MappedType MappedType {
109 get { return mapType; }
110 }
111
112 public object DefaultValue {
113 get { return defaultValue; }
114 }
115
116 public int CompareTo(IFieldDescriptorLite other) {
117 return FieldNumber.CompareTo(other.FieldNumber);
118 }
csharptest804b6d82010-11-07 10:49:33 -0600119 }
csharptest487da482010-11-07 18:49:42 -0600120
121 public class GeneratedRepeatExtensionLite<TContainingType, TExtensionType> : GeneratedExtensionLite<TContainingType, IList<TExtensionType>>
122 where TContainingType : IMessageLite {
csharptest272cb8a2010-11-09 20:49:12 -0600123 public GeneratedRepeatExtensionLite(string fullName, TContainingType containingTypeDefaultInstance,
csharptest487da482010-11-07 18:49:42 -0600124 IMessageLite messageDefaultInstance, IEnumLiteMap enumTypeMap, int number, FieldType type, bool isPacked) :
csharptest272cb8a2010-11-09 20:49:12 -0600125 base(fullName, containingTypeDefaultInstance, new List<TExtensionType>(), messageDefaultInstance, enumTypeMap, number, type, isPacked) {
csharptest487da482010-11-07 18:49:42 -0600126 }
127
128 public override object ToReflectionType(object value) {
csharptest7d396f92010-11-08 20:06:46 -0600129 IList<object> result = new List<object>();
130 foreach (object element in (IEnumerable) value) {
131 result.Add(SingularToReflectionType(element));
132 }
133 return result;
csharptest487da482010-11-07 18:49:42 -0600134 }
135
136 public override object FromReflectionType(object value) {
137 // Must convert the whole list.
138 List<TExtensionType> result = new List<TExtensionType>();
139 foreach (object element in (IEnumerable)value) {
140 result.Add((TExtensionType)SingularFromReflectionType(element));
141 }
142 return result;
143 }
144 }
145
csharptest804b6d82010-11-07 10:49:33 -0600146 public class GeneratedExtensionLite<TContainingType, TExtensionType> : IGeneratedExtensionLite
147 where TContainingType : IMessageLite {
148
149 private readonly TContainingType containingTypeDefaultInstance;
150 private readonly TExtensionType defaultValue;
151 private readonly IMessageLite messageDefaultInstance;
152 private readonly ExtensionDescriptorLite descriptor;
153
154 // We can't always initialize a GeneratedExtension when we first construct
155 // it due to initialization order difficulties (namely, the default
156 // instances may not have been constructed yet). So, we construct an
157 // uninitialized GeneratedExtension once, then call internalInit() on it
158 // later. Generated code will always call internalInit() on all extensions
159 // as part of the static initialization code, and internalInit() throws an
160 // exception if called more than once, so this method is useless to users.
161 protected GeneratedExtensionLite(
162 TContainingType containingTypeDefaultInstance,
163 TExtensionType defaultValue,
164 IMessageLite messageDefaultInstance,
165 ExtensionDescriptorLite descriptor) {
166 this.containingTypeDefaultInstance = containingTypeDefaultInstance;
167 this.messageDefaultInstance = messageDefaultInstance;
168 this.defaultValue = defaultValue;
169 this.descriptor = descriptor;
170 }
171
172 /** For use by generated code only. */
173 public GeneratedExtensionLite(
csharptest272cb8a2010-11-09 20:49:12 -0600174 string fullName,
csharptest804b6d82010-11-07 10:49:33 -0600175 TContainingType containingTypeDefaultInstance,
176 TExtensionType defaultValue,
177 IMessageLite messageDefaultInstance,
csharptest980ba8d2010-11-07 16:30:39 -0600178 IEnumLiteMap enumTypeMap,
csharptest804b6d82010-11-07 10:49:33 -0600179 int number,
180 FieldType type)
181 : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
csharptest272cb8a2010-11-09 20:49:12 -0600182 new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, defaultValue,
csharptest804b6d82010-11-07 10:49:33 -0600183 false /* isRepeated */, false /* isPacked */)) {
184 }
185
csharptest7d396f92010-11-08 20:06:46 -0600186 private static readonly IList<object> Empty = new object[0];
csharptest487da482010-11-07 18:49:42 -0600187 /** Repeating fields: For use by generated code only. */
188 protected GeneratedExtensionLite(
csharptest272cb8a2010-11-09 20:49:12 -0600189 string fullName,
csharptest804b6d82010-11-07 10:49:33 -0600190 TContainingType containingTypeDefaultInstance,
191 TExtensionType defaultValue,
192 IMessageLite messageDefaultInstance,
csharptest980ba8d2010-11-07 16:30:39 -0600193 IEnumLiteMap enumTypeMap,
csharptest804b6d82010-11-07 10:49:33 -0600194 int number,
195 FieldType type,
196 bool isPacked)
197 : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
csharptest272cb8a2010-11-09 20:49:12 -0600198 new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, Empty,
csharptest804b6d82010-11-07 10:49:33 -0600199 true /* isRepeated */, isPacked)) {
200 }
201
202 /// <summary>
csharptest980ba8d2010-11-07 16:30:39 -0600203 /// Returns information about this extension
204 /// </summary>
205 public IFieldDescriptorLite Descriptor {
206 get { return descriptor; }
207 }
208
209 /// <summary>
210 /// Returns the default value for this extension
211 /// </summary>
212 public TExtensionType DefaultValue {
213 get { return defaultValue; }
214 }
215
216 /// <summary>
csharptest804b6d82010-11-07 10:49:33 -0600217 /// used for the extension registry
218 /// </summary>
219 object IGeneratedExtensionLite.ContainingType {
220 get { return ContainingTypeDefaultInstance; }
221 }
222 /**
223 * Default instance of the type being extended, used to identify that type.
224 */
225 public TContainingType ContainingTypeDefaultInstance {
226 get {
227 return containingTypeDefaultInstance;
228 }
229 }
230
231 /** Get the field number. */
232 public int Number {
233 get {
csharptest980ba8d2010-11-07 16:30:39 -0600234 return descriptor.FieldNumber;
csharptest804b6d82010-11-07 10:49:33 -0600235 }
236 }
237 /**
238 * If the extension is an embedded message, this is the default instance of
239 * that type.
240 */
241 public IMessageLite MessageDefaultInstance {
242 get {
243 return messageDefaultInstance;
244 }
245 }
csharptest980ba8d2010-11-07 16:30:39 -0600246
csharptest80824a52010-11-07 17:25:47 -0600247 /// <summary>
248 /// Converts from the type used by the native accessors to the type
249 /// used by reflection accessors. For example, the reflection accessors
250 /// for enums use EnumValueDescriptors but the native accessors use
251 /// the generated enum type.
252 /// </summary>
csharptest487da482010-11-07 18:49:42 -0600253 public virtual object ToReflectionType(object value) {
csharptest80824a52010-11-07 17:25:47 -0600254 return SingularToReflectionType(value);
csharptest80824a52010-11-07 17:25:47 -0600255 }
256
257 /// <summary>
258 /// Like ToReflectionType(object) but for a single element.
259 /// </summary>
csharptest487da482010-11-07 18:49:42 -0600260 public object SingularToReflectionType(object value) {
csharptest80824a52010-11-07 17:25:47 -0600261 return descriptor.MappedType == MappedType.Enum
262 ? descriptor.EnumType.FindValueByNumber((int)value)
263 : value;
264 }
265
csharptest487da482010-11-07 18:49:42 -0600266 public virtual object FromReflectionType(object value) {
csharptest80824a52010-11-07 17:25:47 -0600267 return SingularFromReflectionType(value);
csharptest80824a52010-11-07 17:25:47 -0600268 }
269
csharptest980ba8d2010-11-07 16:30:39 -0600270 public object SingularFromReflectionType(object value) {
csharptest80824a52010-11-07 17:25:47 -0600271 switch (Descriptor.MappedType) {
272 case MappedType.Message:
273 if (value is TExtensionType) {
274 return value;
275 } else {
276 // It seems the copy of the embedded message stored inside the
277 // extended message is not of the exact type the user was
278 // expecting. This can happen if a user defines a
279 // GeneratedExtension manually and gives it a different type.
280 // This should not happen in normal use. But, to be nice, we'll
281 // copy the message to whatever type the caller was expecting.
282 return MessageDefaultInstance.WeakCreateBuilderForType()
283 .WeakMergeFrom((IMessageLite)value).WeakBuild();
284 }
285 case MappedType.Enum:
286 // Just return a boxed int - that can be unboxed to the enum
287 IEnumLite enumValue = (IEnumLite)value;
288 return enumValue.Number;
289 default:
290 return value;
291 }
csharptest980ba8d2010-11-07 16:30:39 -0600292 }
csharptest804b6d82010-11-07 10:49:33 -0600293 }
csharptestd9c59e62010-11-04 19:36:28 -0500294}