Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: third_party/protobuf/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs

Issue 1842653006: Update //third_party/protobuf to version 3. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2008 Google Inc. All rights reserved.
4 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 // * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32
33 using System;
34 using System.Linq;
35 using Google.Protobuf.Compatibility;
36
37 namespace Google.Protobuf.Reflection
38 {
39 /// <summary>
40 /// Descriptor for a field or extension within a message in a .proto file.
41 /// </summary>
42 public sealed class FieldDescriptor : DescriptorBase, IComparable<FieldDescr iptor>
43 {
44 private readonly FieldDescriptorProto proto;
45 private EnumDescriptor enumType;
46 private MessageDescriptor messageType;
47 private readonly MessageDescriptor containingType;
48 private readonly OneofDescriptor containingOneof;
49 private FieldType fieldType;
50 private readonly string propertyName; // Annoyingly, needed in Crosslink .
51 private IFieldAccessor accessor;
52
53 internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file ,
54 MessageDescriptor parent, int index, string pro pertyName)
55 : base(file, file.ComputeFullName(parent, proto.Name), index)
56 {
57 this.proto = proto;
58 if (proto.Type != 0)
59 {
60 fieldType = GetFieldTypeFromProtoType(proto.Type);
61 }
62
63 if (FieldNumber <= 0)
64 {
65 throw new DescriptorValidationException(this, "Field numbers mus t be positive integers.");
66 }
67 containingType = parent;
68 // OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnCo nstruction.
69 if (proto.OneofIndex != -1)
70 {
71 if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.One ofDecl.Count)
72 {
73 throw new DescriptorValidationException(this,
74 $"FieldDescriptorProto.oneof_index is out of range for t ype {parent.Name}");
75 }
76 containingOneof = parent.Oneofs[proto.OneofIndex];
77 }
78
79 file.DescriptorPool.AddSymbol(this);
80 // We can't create the accessor until we've cross-linked, unfortunat ely, as we
81 // may not know whether the type of the field is a map or not. Remem ber the property name
82 // for later.
83 // We could trust the generated code and check whether the type of t he property is
84 // a MapField, but that feels a tad nasty.
85 this.propertyName = propertyName;
86 }
87
88 /// <summary>
89 /// The brief name of the descriptor's target.
90 /// </summary>
91 public override string Name { get { return proto.Name; } }
92
93 internal FieldDescriptorProto Proto { get { return proto; } }
94
95 /// <summary>
96 /// Returns the accessor for this field.
97 /// </summary>
98 /// <remarks>
99 /// <para>
100 /// While a <see cref="FieldDescriptor"/> describes the field, it does n ot provide
101 /// any way of obtaining or changing the value of the field within a spe cific message;
102 /// that is the responsibility of the accessor.
103 /// </para>
104 /// <para>
105 /// The value returned by this property will be non-null for all regular fields. However,
106 /// if a message containing a map field is introspected, the list of nes ted messages will include
107 /// an auto-generated nested key/value pair message for the field. This is not represented in any
108 /// generated type, and the value of the map field itself is represented by a dictionary in the
109 /// reflection API. There are never instances of those "hidden" messages , so no accessor is provided
110 /// and this property will return null.
111 /// </para>
112 /// </remarks>
113 public IFieldAccessor Accessor { get { return accessor; } }
114
115 /// <summary>
116 /// Maps a field type as included in the .proto file to a FieldType.
117 /// </summary>
118 private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto. Types.Type type)
119 {
120 switch (type)
121 {
122 case FieldDescriptorProto.Types.Type.TYPE_DOUBLE:
123 return FieldType.Double;
124 case FieldDescriptorProto.Types.Type.TYPE_FLOAT:
125 return FieldType.Float;
126 case FieldDescriptorProto.Types.Type.TYPE_INT64:
127 return FieldType.Int64;
128 case FieldDescriptorProto.Types.Type.TYPE_UINT64:
129 return FieldType.UInt64;
130 case FieldDescriptorProto.Types.Type.TYPE_INT32:
131 return FieldType.Int32;
132 case FieldDescriptorProto.Types.Type.TYPE_FIXED64:
133 return FieldType.Fixed64;
134 case FieldDescriptorProto.Types.Type.TYPE_FIXED32:
135 return FieldType.Fixed32;
136 case FieldDescriptorProto.Types.Type.TYPE_BOOL:
137 return FieldType.Bool;
138 case FieldDescriptorProto.Types.Type.TYPE_STRING:
139 return FieldType.String;
140 case FieldDescriptorProto.Types.Type.TYPE_GROUP:
141 return FieldType.Group;
142 case FieldDescriptorProto.Types.Type.TYPE_MESSAGE:
143 return FieldType.Message;
144 case FieldDescriptorProto.Types.Type.TYPE_BYTES:
145 return FieldType.Bytes;
146 case FieldDescriptorProto.Types.Type.TYPE_UINT32:
147 return FieldType.UInt32;
148 case FieldDescriptorProto.Types.Type.TYPE_ENUM:
149 return FieldType.Enum;
150 case FieldDescriptorProto.Types.Type.TYPE_SFIXED32:
151 return FieldType.SFixed32;
152 case FieldDescriptorProto.Types.Type.TYPE_SFIXED64:
153 return FieldType.SFixed64;
154 case FieldDescriptorProto.Types.Type.TYPE_SINT32:
155 return FieldType.SInt32;
156 case FieldDescriptorProto.Types.Type.TYPE_SINT64:
157 return FieldType.SInt64;
158 default:
159 throw new ArgumentException("Invalid type specified");
160 }
161 }
162
163 /// <summary>
164 /// Returns <c>true</c> if this field is a repeated field; <c>false</c> otherwise.
165 /// </summary>
166 public bool IsRepeated
167 {
168 get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_R EPEATED; }
169 }
170
171 /// <summary>
172 /// Returns <c>true</c> if this field is a map field; <c>false</c> other wise.
173 /// </summary>
174 public bool IsMap
175 {
176 get { return fieldType == FieldType.Message && messageType.Proto.Opt ions != null && messageType.Proto.Options.MapEntry; }
177 }
178
179 /// <summary>
180 /// Returns <c>true</c> if this field is a packed, repeated field; <c>fa lse</c> otherwise.
181 /// </summary>
182 public bool IsPacked
183 {
184 // Note the || rather than && here - we're effectively defaulting to packed, because that *is*
185 // the default in proto3, which is all we support. We may give the w rong result for the protos
186 // within descriptor.proto, but that's okay, as they're never expose d and we don't use IsPacked
187 // within the runtime.
188 get { return Proto.Options == null || Proto.Options.Packed; }
189 }
190
191 /// <summary>
192 /// Get the field's containing message type.
193 /// </summary>
194 public MessageDescriptor ContainingType
195 {
196 get { return containingType; }
197 }
198
199 /// <summary>
200 /// Returns the oneof containing this field, or <c>null</c> if it is not part of a oneof.
201 /// </summary>
202 public OneofDescriptor ContainingOneof
203 {
204 get { return containingOneof; }
205 }
206
207 /// <summary>
208 /// Returns the type of the field.
209 /// </summary>
210 public FieldType FieldType
211 {
212 get { return fieldType; }
213 }
214
215 /// <summary>
216 /// Returns the field number declared in the proto file.
217 /// </summary>
218 public int FieldNumber
219 {
220 get { return Proto.Number; }
221 }
222
223 /// <summary>
224 /// Compares this descriptor with another one, ordering in "canonical" o rder
225 /// which simply means ascending order by field number. <paramref name=" other"/>
226 /// must be a field of the same type, i.e. the <see cref="ContainingType "/> of
227 /// both fields must be the same.
228 /// </summary>
229 public int CompareTo(FieldDescriptor other)
230 {
231 if (other.containingType != containingType)
232 {
233 throw new ArgumentException("FieldDescriptors can only be compar ed to other FieldDescriptors " +
234 "for fields of the same message type .");
235 }
236 return FieldNumber - other.FieldNumber;
237 }
238
239 /// <summary>
240 /// For enum fields, returns the field's type.
241 /// </summary>
242 public EnumDescriptor EnumType
243 {
244 get
245 {
246 if (fieldType != FieldType.Enum)
247 {
248 throw new InvalidOperationException("EnumType is only valid for enum fields.");
249 }
250 return enumType;
251 }
252 }
253
254 /// <summary>
255 /// For embedded message and group fields, returns the field's type.
256 /// </summary>
257 public MessageDescriptor MessageType
258 {
259 get
260 {
261 if (fieldType != FieldType.Message)
262 {
263 throw new InvalidOperationException("MessageType is only val id for message fields.");
264 }
265 return messageType;
266 }
267 }
268
269 /// <summary>
270 /// Look up and cross-link all field types etc.
271 /// </summary>
272 internal void CrossLink()
273 {
274 if (Proto.TypeName != "")
275 {
276 IDescriptor typeDescriptor =
277 File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
278
279 if (Proto.Type != 0)
280 {
281 // Choose field type based on symbol.
282 if (typeDescriptor is MessageDescriptor)
283 {
284 fieldType = FieldType.Message;
285 }
286 else if (typeDescriptor is EnumDescriptor)
287 {
288 fieldType = FieldType.Enum;
289 }
290 else
291 {
292 throw new DescriptorValidationException(this, $"\"{Proto .TypeName}\" is not a type.");
293 }
294 }
295
296 if (fieldType == FieldType.Message)
297 {
298 if (!(typeDescriptor is MessageDescriptor))
299 {
300 throw new DescriptorValidationException(this, $"\"{Proto .TypeName}\" is not a message type.");
301 }
302 messageType = (MessageDescriptor) typeDescriptor;
303
304 if (Proto.DefaultValue != "")
305 {
306 throw new DescriptorValidationException(this, "Messages can't have default values.");
307 }
308 }
309 else if (fieldType == FieldType.Enum)
310 {
311 if (!(typeDescriptor is EnumDescriptor))
312 {
313 throw new DescriptorValidationException(this, $"\"{Proto .TypeName}\" is not an enum type.");
314 }
315 enumType = (EnumDescriptor) typeDescriptor;
316 }
317 else
318 {
319 throw new DescriptorValidationException(this, "Field with pr imitive type has type_name.");
320 }
321 }
322 else
323 {
324 if (fieldType == FieldType.Message || fieldType == FieldType.Enu m)
325 {
326 throw new DescriptorValidationException(this, "Field with me ssage or enum type missing type_name.");
327 }
328 }
329
330 // Note: no attempt to perform any default value parsing
331
332 File.DescriptorPool.AddFieldByNumber(this);
333
334 if (containingType != null && containingType.Proto.Options != null & & containingType.Proto.Options.MessageSetWireFormat)
335 {
336 throw new DescriptorValidationException(this, "MessageSet format is not supported.");
337 }
338 accessor = CreateAccessor(propertyName);
339 }
340
341 private IFieldAccessor CreateAccessor(string propertyName)
342 {
343 // If we're given no property name, that's because we really don't w ant an accessor.
344 // (At the moment, that means it's a map entry message...)
345 if (propertyName == null)
346 {
347 return null;
348 }
349 var property = containingType.ClrType.GetProperty(propertyName);
350 if (property == null)
351 {
352 throw new DescriptorValidationException(this, $"Property {proper tyName} not found in {containingType.ClrType}");
353 }
354 return IsMap ? new MapFieldAccessor(property, this)
355 : IsRepeated ? new RepeatedFieldAccessor(property, this)
356 : (IFieldAccessor) new SingleFieldAccessor(property, this);
357 }
358 }
359 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698