DescriptorMessageInfoFactory.java
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import static com.google.protobuf.FieldInfo.forField;
34 import static com.google.protobuf.FieldInfo.forFieldWithEnumVerifier;
35 import static com.google.protobuf.FieldInfo.forMapField;
36 import static com.google.protobuf.FieldInfo.forOneofMemberField;
37 import static com.google.protobuf.FieldInfo.forPackedField;
38 import static com.google.protobuf.FieldInfo.forPackedFieldWithEnumVerifier;
39 import static com.google.protobuf.FieldInfo.forProto2OptionalField;
40 import static com.google.protobuf.FieldInfo.forProto2RequiredField;
41 import static com.google.protobuf.FieldInfo.forRepeatedMessageField;
42 
47 import java.lang.reflect.Field;
48 import java.lang.reflect.Method;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.HashMap;
52 import java.util.HashSet;
53 import java.util.List;
54 import java.util.Map;
55 import java.util.Set;
56 import java.util.Stack;
57 import java.util.concurrent.ConcurrentHashMap;
58 
60 @ExperimentalApi
61 final class DescriptorMessageInfoFactory implements MessageInfoFactory {
62  private static final String GET_DEFAULT_INSTANCE_METHOD_NAME = "getDefaultInstance";
63  private static final DescriptorMessageInfoFactory instance = new DescriptorMessageInfoFactory();
64  private static final Set<String> specialFieldNames =
65  new HashSet<>(Arrays.asList("cached_size", "serialized_size", "class"));
66 
67  // Disallow construction - it's a singleton.
68  private DescriptorMessageInfoFactory() {}
69 
70  public static DescriptorMessageInfoFactory getInstance() {
71  return instance;
72  }
73 
74  @Override
75  public boolean isSupported(Class<?> messageType) {
76  return GeneratedMessageV3.class.isAssignableFrom(messageType);
77  }
78 
79  @Override
80  public MessageInfo messageInfoFor(Class<?> messageType) {
81  if (!GeneratedMessageV3.class.isAssignableFrom(messageType)) {
82  throw new IllegalArgumentException("Unsupported message type: " + messageType.getName());
83  }
84 
85  return convert(messageType, descriptorForType(messageType));
86  }
87 
88  private static Message getDefaultInstance(Class<?> messageType) {
89  try {
90  Method method = messageType.getDeclaredMethod(GET_DEFAULT_INSTANCE_METHOD_NAME);
91  return (Message) method.invoke(null);
92  } catch (Exception e) {
93  throw new IllegalArgumentException(
94  "Unable to get default instance for message class " + messageType.getName(), e);
95  }
96  }
97 
98  private static Descriptor descriptorForType(Class<?> messageType) {
99  return getDefaultInstance(messageType).getDescriptorForType();
100  }
101 
102  private static MessageInfo convert(Class<?> messageType, Descriptor messageDescriptor) {
103  switch (messageDescriptor.getFile().getSyntax()) {
104  case PROTO2:
105  return convertProto2(messageType, messageDescriptor);
106  case PROTO3:
107  return convertProto3(messageType, messageDescriptor);
108  default:
109  throw new IllegalArgumentException(
110  "Unsupported syntax: " + messageDescriptor.getFile().getSyntax());
111  }
112  }
113 
128  static class IsInitializedCheckAnalyzer {
129 
130  private final Map<Descriptor, Boolean> resultCache =
131  new ConcurrentHashMap<Descriptor, Boolean>();
132 
133  // The following data members are part of Tarjan's SCC algorithm. See:
134  // https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
135  private int index = 0;
136  private final Stack<Node> stack = new Stack<Node>();
137  private final Map<Descriptor, Node> nodeCache = new HashMap<Descriptor, Node>();
138 
139  public boolean needsIsInitializedCheck(Descriptor descriptor) {
140  Boolean cachedValue = resultCache.get(descriptor);
141  if (cachedValue != null) {
142  return cachedValue;
143  }
144  synchronized (this) {
145  // Double-check the cache because some other thread may have updated it while we
146  // were acquiring the lock.
147  cachedValue = resultCache.get(descriptor);
148  if (cachedValue != null) {
149  return cachedValue;
150  }
151  return dfs(descriptor).component.needsIsInitializedCheck;
152  }
153  }
154 
155  private static class Node {
156  final Descriptor descriptor;
157  final int index;
158  int lowLink;
159  StronglyConnectedComponent component; // null if the node is still on stack.
160 
162  this.descriptor = descriptor;
163  this.index = index;
164  this.lowLink = index;
165  this.component = null;
166  }
167  }
168 
169  private static class StronglyConnectedComponent {
170  final List<Descriptor> messages = new ArrayList<Descriptor>();
171  boolean needsIsInitializedCheck = false;
172  }
173 
174  private Node dfs(Descriptor descriptor) {
175  Node result = new Node(descriptor, index++);
176  stack.push(result);
177  nodeCache.put(descriptor, result);
178 
179  // Recurse the fields / nodes in graph
180  for (FieldDescriptor field : descriptor.getFields()) {
181  if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
182  Node child = nodeCache.get(field.getMessageType());
183  if (child == null) {
184  // Unexplored node
185  child = dfs(field.getMessageType());
186  result.lowLink = Math.min(result.lowLink, child.lowLink);
187  } else {
188  if (child.component == null) {
189  // Still in the stack so we found a back edge.
190  result.lowLink = Math.min(result.lowLink, child.lowLink);
191  }
192  }
193  }
194  }
195 
196  if (result.index == result.lowLink) {
197  // This is the root of a strongly connected component.
198  StronglyConnectedComponent component = new StronglyConnectedComponent();
199  while (true) {
200  Node node = stack.pop();
201  node.component = component;
202  component.messages.add(node.descriptor);
203  if (node == result) {
204  break;
205  }
206  }
207 
208  analyze(component);
209  }
210 
211  return result;
212  }
213 
214  // Determine whether messages in this SCC needs isInitialized check.
215  private void analyze(StronglyConnectedComponent component) {
216  boolean needsIsInitializedCheck = false;
217  loop:
218  for (Descriptor descriptor : component.messages) {
219  if (descriptor.isExtendable()) {
220  needsIsInitializedCheck = true;
221  break;
222  }
223 
224  for (FieldDescriptor field : descriptor.getFields()) {
225  if (field.isRequired()) {
226  needsIsInitializedCheck = true;
227  break loop;
228  }
229 
230  if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
231  // Since we are analyzing the graph bottom-up, all referenced fields should either be
232  // in this same component or in a different already-analyzed component.
233  Node node = nodeCache.get(field.getMessageType());
234  if (node.component != component) {
235  if (node.component.needsIsInitializedCheck) {
236  needsIsInitializedCheck = true;
237  break loop;
238  }
239  }
240  }
241  }
242  }
243 
244  component.needsIsInitializedCheck = needsIsInitializedCheck;
245 
246  for (Descriptor descriptor : component.messages) {
247  resultCache.put(descriptor, component.needsIsInitializedCheck);
248  }
249  }
250  }
251 
252  private static IsInitializedCheckAnalyzer isInitializedCheckAnalyzer =
253  new IsInitializedCheckAnalyzer();
254 
255  private static boolean needsIsInitializedCheck(Descriptor descriptor) {
256  return isInitializedCheckAnalyzer.needsIsInitializedCheck(descriptor);
257  }
258 
259  private static StructuralMessageInfo convertProto2(
260  Class<?> messageType, Descriptor messageDescriptor) {
261  List<FieldDescriptor> fieldDescriptors = messageDescriptor.getFields();
262  StructuralMessageInfo.Builder builder =
263  StructuralMessageInfo.newBuilder(fieldDescriptors.size());
264  builder.withDefaultInstance(getDefaultInstance(messageType));
265  builder.withSyntax(ProtoSyntax.PROTO2);
266  builder.withMessageSetWireFormat(messageDescriptor.getOptions().getMessageSetWireFormat());
267 
268  OneofState oneofState = new OneofState();
269  int bitFieldIndex = 0;
270  int presenceMask = 1;
271  Field bitField = null;
272 
273  // Fields in the descriptor are ordered by the index position in which they appear in the
274  // proto file. This is the same order used to determine the presence mask used in the
275  // bitFields. So to determine the appropriate presence mask to be used for a field, we simply
276  // need to shift the presence mask whenever a presence-checked field is encountered.
277  for (int i = 0; i < fieldDescriptors.size(); ++i) {
278  final FieldDescriptor fd = fieldDescriptors.get(i);
279  boolean enforceUtf8 = fd.getFile().getOptions().getJavaStringCheckUtf8();
280  Internal.EnumVerifier enumVerifier = null;
281  if (fd.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
282  enumVerifier =
283  new Internal.EnumVerifier() {
284  @Override
285  public boolean isInRange(int number) {
286  return fd.getEnumType().findValueByNumber(number) != null;
287  }
288  };
289  }
290  if (fd.getContainingOneof() != null) {
291  // Build a oneof member field.
292  builder.withField(buildOneofMember(messageType, fd, oneofState, enforceUtf8, enumVerifier));
293  } else {
294  Field field = field(messageType, fd);
295  int number = fd.getNumber();
296  FieldType type = getFieldType(fd);
297 
298  if (fd.isMapField()) {
299  // Map field points to an auto-generated message entry type with the definition:
300  // message MapEntry {
301  // K key = 1;
302  // V value = 2;
303  // }
304  final FieldDescriptor valueField = fd.getMessageType().findFieldByNumber(2);
305  if (valueField.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
306  enumVerifier =
307  new Internal.EnumVerifier() {
308  @Override
309  public boolean isInRange(int number) {
310  return valueField.getEnumType().findValueByNumber(number) != null;
311  }
312  };
313  }
314  builder.withField(
315  forMapField(
316  field,
317  number,
318  SchemaUtil.getMapDefaultEntry(messageType, fd.getName()),
319  enumVerifier));
320  continue;
321  }
322 
323  if (fd.isRepeated()) {
324  // Repeated fields are not presence-checked.
325  if (enumVerifier != null) {
326  if (fd.isPacked()) {
327  builder.withField(
328  forPackedFieldWithEnumVerifier(
329  field, number, type, enumVerifier, cachedSizeField(messageType, fd)));
330  } else {
331  builder.withField(forFieldWithEnumVerifier(field, number, type, enumVerifier));
332  }
333  } else if (fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
334  builder.withField(
335  forRepeatedMessageField(
336  field, number, type, getTypeForRepeatedMessageField(messageType, fd)));
337  } else {
338  if (fd.isPacked()) {
339  builder.withField(
340  forPackedField(field, number, type, cachedSizeField(messageType, fd)));
341  } else {
342  builder.withField(forField(field, number, type, enforceUtf8));
343  }
344  }
345  continue;
346  }
347 
348  if (bitField == null) {
349  // Lazy-create the next bitfield since we know it must exist.
350  bitField = bitField(messageType, bitFieldIndex);
351  }
352 
353  // It's a presence-checked field.
354  if (fd.isRequired()) {
355  builder.withField(
356  forProto2RequiredField(
357  field, number, type, bitField, presenceMask, enforceUtf8, enumVerifier));
358  } else {
359  builder.withField(
360  forProto2OptionalField(
361  field, number, type, bitField, presenceMask, enforceUtf8, enumVerifier));
362  }
363  }
364 
365  // Update the presence mask for the next iteration. If the shift clears out the mask, we will
366  // go to the next bitField.
367  presenceMask <<= 1;
368  if (presenceMask == 0) {
369  bitField = null;
370  presenceMask = 1;
371  bitFieldIndex++;
372  }
373  }
374 
375  List<Integer> fieldsToCheckIsInitialized = new ArrayList<Integer>();
376  for (int i = 0; i < fieldDescriptors.size(); ++i) {
377  FieldDescriptor fd = fieldDescriptors.get(i);
378  if (fd.isRequired()
379  || (fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE
380  && needsIsInitializedCheck(fd.getMessageType()))) {
381  fieldsToCheckIsInitialized.add(fd.getNumber());
382  }
383  }
384  int[] numbers = new int[fieldsToCheckIsInitialized.size()];
385  for (int i = 0; i < fieldsToCheckIsInitialized.size(); i++) {
386  numbers[i] = fieldsToCheckIsInitialized.get(i);
387  }
388  builder.withCheckInitialized(numbers);
389 
390  return builder.build();
391  }
392 
393  private static StructuralMessageInfo convertProto3(
394  Class<?> messageType, Descriptor messageDescriptor) {
395  List<FieldDescriptor> fieldDescriptors = messageDescriptor.getFields();
396  StructuralMessageInfo.Builder builder =
397  StructuralMessageInfo.newBuilder(fieldDescriptors.size());
398  builder.withDefaultInstance(getDefaultInstance(messageType));
399  builder.withSyntax(ProtoSyntax.PROTO3);
400 
401  OneofState oneofState = new OneofState();
402  boolean enforceUtf8 = true;
403  for (int i = 0; i < fieldDescriptors.size(); ++i) {
404  FieldDescriptor fd = fieldDescriptors.get(i);
405  if (fd.getContainingOneof() != null) {
406  // Build a oneof member field.
407  builder.withField(buildOneofMember(messageType, fd, oneofState, enforceUtf8, null));
408  continue;
409  }
410  if (fd.isMapField()) {
411  builder.withField(
412  forMapField(
413  field(messageType, fd),
414  fd.getNumber(),
415  SchemaUtil.getMapDefaultEntry(messageType, fd.getName()),
416  null));
417  continue;
418  }
419  if (fd.isRepeated() && fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
420  builder.withField(
421  forRepeatedMessageField(
422  field(messageType, fd),
423  fd.getNumber(),
424  getFieldType(fd),
425  getTypeForRepeatedMessageField(messageType, fd)));
426  continue;
427  }
428  if (fd.isPacked()) {
429  builder.withField(
430  forPackedField(
431  field(messageType, fd),
432  fd.getNumber(),
433  getFieldType(fd),
434  cachedSizeField(messageType, fd)));
435  } else {
436  builder.withField(
437  forField(field(messageType, fd), fd.getNumber(), getFieldType(fd), enforceUtf8));
438  }
439  }
440 
441  return builder.build();
442  }
443 
445  private static FieldInfo buildOneofMember(
446  Class<?> messageType,
447  FieldDescriptor fd,
448  OneofState oneofState,
449  boolean enforceUtf8,
450  Internal.EnumVerifier enumVerifier) {
451  OneofInfo oneof = oneofState.getOneof(messageType, fd.getContainingOneof());
452  FieldType type = getFieldType(fd);
453  Class<?> oneofStoredType = getOneofStoredType(messageType, fd, type);
454  return forOneofMemberField(
455  fd.getNumber(), type, oneof, oneofStoredType, enforceUtf8, enumVerifier);
456  }
457 
458  private static Class<?> getOneofStoredType(
459  Class<?> messageType, FieldDescriptor fd, FieldType type) {
460  switch (type.getJavaType()) {
461  case BOOLEAN:
462  return Boolean.class;
463  case BYTE_STRING:
464  return ByteString.class;
465  case DOUBLE:
466  return Double.class;
467  case FLOAT:
468  return Float.class;
469  case ENUM:
470  case INT:
471  return Integer.class;
472  case LONG:
473  return Long.class;
474  case STRING:
475  return String.class;
476  case MESSAGE:
477  return getOneofStoredTypeForMessage(messageType, fd);
478  default:
479  throw new IllegalArgumentException("Invalid type for oneof: " + type);
480  }
481  }
482 
483  private static FieldType getFieldType(FieldDescriptor fd) {
484  switch (fd.getType()) {
485  case BOOL:
486  if (!fd.isRepeated()) {
487  return FieldType.BOOL;
488  }
489  return fd.isPacked() ? FieldType.BOOL_LIST_PACKED : FieldType.BOOL_LIST;
490  case BYTES:
491  return fd.isRepeated() ? FieldType.BYTES_LIST : FieldType.BYTES;
492  case DOUBLE:
493  if (!fd.isRepeated()) {
494  return FieldType.DOUBLE;
495  }
496  return fd.isPacked() ? FieldType.DOUBLE_LIST_PACKED : FieldType.DOUBLE_LIST;
497  case ENUM:
498  if (!fd.isRepeated()) {
499  return FieldType.ENUM;
500  }
501  return fd.isPacked() ? FieldType.ENUM_LIST_PACKED : FieldType.ENUM_LIST;
502  case FIXED32:
503  if (!fd.isRepeated()) {
504  return FieldType.FIXED32;
505  }
506  return fd.isPacked() ? FieldType.FIXED32_LIST_PACKED : FieldType.FIXED32_LIST;
507  case FIXED64:
508  if (!fd.isRepeated()) {
509  return FieldType.FIXED64;
510  }
511  return fd.isPacked() ? FieldType.FIXED64_LIST_PACKED : FieldType.FIXED64_LIST;
512  case FLOAT:
513  if (!fd.isRepeated()) {
514  return FieldType.FLOAT;
515  }
516  return fd.isPacked() ? FieldType.FLOAT_LIST_PACKED : FieldType.FLOAT_LIST;
517  case GROUP:
518  return fd.isRepeated() ? FieldType.GROUP_LIST : FieldType.GROUP;
519  case INT32:
520  if (!fd.isRepeated()) {
521  return FieldType.INT32;
522  }
523  return fd.isPacked() ? FieldType.INT32_LIST_PACKED : FieldType.INT32_LIST;
524  case INT64:
525  if (!fd.isRepeated()) {
526  return FieldType.INT64;
527  }
528  return fd.isPacked() ? FieldType.INT64_LIST_PACKED : FieldType.INT64_LIST;
529  case MESSAGE:
530  if (fd.isMapField()) {
531  return FieldType.MAP;
532  }
533  return fd.isRepeated() ? FieldType.MESSAGE_LIST : FieldType.MESSAGE;
534  case SFIXED32:
535  if (!fd.isRepeated()) {
536  return FieldType.SFIXED32;
537  }
538  return fd.isPacked() ? FieldType.SFIXED32_LIST_PACKED : FieldType.SFIXED32_LIST;
539  case SFIXED64:
540  if (!fd.isRepeated()) {
541  return FieldType.SFIXED64;
542  }
543  return fd.isPacked() ? FieldType.SFIXED64_LIST_PACKED : FieldType.SFIXED64_LIST;
544  case SINT32:
545  if (!fd.isRepeated()) {
546  return FieldType.SINT32;
547  }
548  return fd.isPacked() ? FieldType.SINT32_LIST_PACKED : FieldType.SINT32_LIST;
549  case SINT64:
550  if (!fd.isRepeated()) {
551  return FieldType.SINT64;
552  }
553  return fd.isPacked() ? FieldType.SINT64_LIST_PACKED : FieldType.SINT64_LIST;
554  case STRING:
555  return fd.isRepeated() ? FieldType.STRING_LIST : FieldType.STRING;
556  case UINT32:
557  if (!fd.isRepeated()) {
558  return FieldType.UINT32;
559  }
560  return fd.isPacked() ? FieldType.UINT32_LIST_PACKED : FieldType.UINT32_LIST;
561  case UINT64:
562  if (!fd.isRepeated()) {
563  return FieldType.UINT64;
564  }
565  return fd.isPacked() ? FieldType.UINT64_LIST_PACKED : FieldType.UINT64_LIST;
566  default:
567  throw new IllegalArgumentException("Unsupported field type: " + fd.getType());
568  }
569  }
570 
571  private static Field bitField(Class<?> messageType, int index) {
572  return field(messageType, "bitField" + index + "_");
573  }
574 
575  private static Field field(Class<?> messageType, FieldDescriptor fd) {
576  return field(messageType, getFieldName(fd));
577  }
578 
579  private static Field cachedSizeField(Class<?> messageType, FieldDescriptor fd) {
580  return field(messageType, getCachedSizeFieldName(fd));
581  }
582 
583  private static Field field(Class<?> messageType, String fieldName) {
584  try {
585  return messageType.getDeclaredField(fieldName);
586  } catch (Exception e) {
587  throw new IllegalArgumentException(
588  "Unable to find field " + fieldName + " in message class " + messageType.getName());
589  }
590  }
591 
592  static String getFieldName(FieldDescriptor fd) {
593  String name = (fd.getType() == FieldDescriptor.Type.GROUP)
594  ? fd.getMessageType().getName()
595  : fd.getName();
596  String suffix = specialFieldNames.contains(name) ? "__" : "_";
597  return snakeCaseToCamelCase(name) + suffix;
598  }
599 
600  private static String getCachedSizeFieldName(FieldDescriptor fd) {
601  return snakeCaseToCamelCase(fd.getName()) + "MemoizedSerializedSize";
602  }
603 
608  private static String snakeCaseToCamelCase(String snakeCase) {
609  StringBuilder sb = new StringBuilder(snakeCase.length() + 1);
610  boolean capNext = false;
611  for (int ctr = 0; ctr < snakeCase.length(); ctr++) {
612  char next = snakeCase.charAt(ctr);
613  if (next == '_') {
614  capNext = true;
615  } else if (Character.isDigit(next)) {
616  sb.append(next);
617  capNext = true;
618  } else if (capNext) {
619  sb.append(Character.toUpperCase(next));
620  capNext = false;
621  } else if (ctr == 0) {
622  sb.append(Character.toLowerCase(next));
623  } else {
624  sb.append(next);
625  }
626  }
627  return sb.toString();
628  }
629 
633  private static Class<?> getOneofStoredTypeForMessage(Class<?> messageType, FieldDescriptor fd) {
634  try {
635  String name = fd.getType() == Type.GROUP ? fd.getMessageType().getName() : fd.getName();
636  Method getter = messageType.getDeclaredMethod(getterForField(name));
637  return getter.getReturnType();
638  } catch (Exception e) {
639  throw new RuntimeException(e);
640  }
641  }
642 
644  private static Class<?> getTypeForRepeatedMessageField(Class<?> messageType, FieldDescriptor fd) {
645  try {
646  String name = fd.getType() == Type.GROUP ? fd.getMessageType().getName() : fd.getName();
647  Method getter = messageType.getDeclaredMethod(getterForField(name), int.class);
648  return getter.getReturnType();
649  } catch (Exception e) {
650  throw new RuntimeException(e);
651  }
652  }
653 
655  private static String getterForField(String snakeCase) {
656  String camelCase = snakeCaseToCamelCase(snakeCase);
657  StringBuilder builder = new StringBuilder("get");
658  // Capitalize the first character in the field name.
659  builder.append(Character.toUpperCase(camelCase.charAt(0)));
660  builder.append(camelCase.substring(1, camelCase.length()));
661  return builder.toString();
662  }
663 
664  private static final class OneofState {
665  private OneofInfo[] oneofs = new OneofInfo[2];
666 
667  OneofInfo getOneof(Class<?> messageType, OneofDescriptor desc) {
668  int index = desc.getIndex();
669  if (index >= oneofs.length) {
670  // Grow the array.
671  oneofs = Arrays.copyOf(oneofs, index * 2);
672  }
673  OneofInfo info = oneofs[index];
674  if (info == null) {
675  info = newInfo(messageType, desc);
676  oneofs[index] = info;
677  }
678  return info;
679  }
680 
681  private static OneofInfo newInfo(Class<?> messageType, OneofDescriptor desc) {
682  String camelCase = snakeCaseToCamelCase(desc.getName());
683  String valueFieldName = camelCase + "_";
684  String caseFieldName = camelCase + "Case_";
685 
686  return new OneofInfo(
687  desc.getIndex(), field(messageType, caseFieldName), field(messageType, valueFieldName));
688  }
689  }
690 }
com.google.protobuf.Descriptors
Definition: Descriptors.java:80
java::lang
name
GLuint const GLchar * name
Definition: glcorearb.h:3055
java::lang::reflect::Method
Map
Definition: ruby/ext/google/protobuf_c/protobuf.h:442
com.google.protobuf.DescriptorMessageInfoFactory.IsInitializedCheckAnalyzer.Node
Definition: DescriptorMessageInfoFactory.java:155
desc
#define desc
Definition: extension_set.h:342
com.google.protobuf
Definition: ProtoCaliperBenchmark.java:2
descriptor
Descriptor * descriptor
Definition: php/ext/google/protobuf/protobuf.h:936
java::lang::reflect
com.google.protobuf.Descriptors.FieldDescriptor.Type
Definition: Descriptors.java:1215
Descriptor
Definition: ruby/ext/google/protobuf_c/protobuf.h:113
testing::internal::Double
FloatingPoint< double > Double
Definition: gtest-internal.h:429
FieldDescriptor
Definition: ruby/ext/google/protobuf_c/protobuf.h:129
com.google.protobuf.FieldInfo
Definition: FieldInfo.java:40
com.google.protobuf.DescriptorMessageInfoFactory.OneofState.oneofs
OneofInfo[] oneofs
Definition: DescriptorMessageInfoFactory.java:665
Type
Definition: type.pb.h:182
com.google.protobuf.Descriptors.OneofDescriptor
Definition: Descriptors.java:2597
testing::internal::Float
FloatingPoint< float > Float
Definition: gtest-internal.h:428
sb
void * sb
Definition: test_channel.cpp:8
com.google.protobuf.Descriptors.FieldDescriptor.JavaType
Definition: Descriptors.java:1262
googletest-filter-unittest.child
child
Definition: googletest-filter-unittest.py:62
field
const FieldDescriptor * field
Definition: parser_unittest.cc:2694
i
int i
Definition: gmock-matchers_test.cc:764
java
com.google.protobuf.Descriptors.Descriptor
Definition: Descriptors.java:629
type
GLenum type
Definition: glcorearb.h:2695
com.google.protobuf.DescriptorMessageInfoFactory.IsInitializedCheckAnalyzer.StronglyConnectedComponent
Definition: DescriptorMessageInfoFactory.java:169
com.google
com
com.google.protobuf.DescriptorMessageInfoFactory.OneofState
Definition: DescriptorMessageInfoFactory.java:664
com.google.protobuf.DescriptorMessageInfoFactory.OneofState.newInfo
static OneofInfo newInfo(Class<?> messageType, OneofDescriptor desc)
Definition: DescriptorMessageInfoFactory.java:681
next
static size_t next(const upb_table *t, size_t i)
Definition: php/ext/google/protobuf/upb.c:4889
Field
Definition: type.pb.h:416
google::protobuf.internal::FieldType
uint8 FieldType
Definition: extension_set.h:87
index
GLuint index
Definition: glcorearb.h:3055
Method
Definition: api.pb.h:285
number
double number
Definition: cJSON.h:326
google::protobuf::method
const Descriptor::ReservedRange const EnumValueDescriptor method
Definition: src/google/protobuf/descriptor.h:1973
com.google.protobuf.Descriptors.FieldDescriptor
Definition: Descriptors.java:949
com.google.protobuf.Descriptors.FieldDescriptor.JavaType.MESSAGE
MESSAGE
Definition: Descriptors.java:1271


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:50