• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 package com.google.protobuf;
9 
10 import java.io.IOException;
11 
12 @ExperimentalApi
13 @CheckReturnValue
14 abstract class UnknownFieldSchema<T, B> {
15 
16   static final int DEFAULT_RECURSION_LIMIT = 100;
17 
18   @SuppressWarnings("NonFinalStaticField")
19   private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT;
20 
21   /** Whether unknown fields should be dropped. */
shouldDiscardUnknownFields(Reader reader)22   abstract boolean shouldDiscardUnknownFields(Reader reader);
23 
24   /** Adds a varint value to the unknown fields. */
addVarint(B fields, int number, long value)25   abstract void addVarint(B fields, int number, long value);
26 
27   /** Adds a fixed32 value to the unknown fields. */
addFixed32(B fields, int number, int value)28   abstract void addFixed32(B fields, int number, int value);
29 
30   /** Adds a fixed64 value to the unknown fields. */
addFixed64(B fields, int number, long value)31   abstract void addFixed64(B fields, int number, long value);
32 
33   /** Adds a length delimited value to the unknown fields. */
addLengthDelimited(B fields, int number, ByteString value)34   abstract void addLengthDelimited(B fields, int number, ByteString value);
35 
36   /** Adds a group value to the unknown fields. */
addGroup(B fields, int number, T subFieldSet)37   abstract void addGroup(B fields, int number, T subFieldSet);
38 
39   /** Create a new builder for unknown fields. */
newBuilder()40   abstract B newBuilder();
41 
42   /** Returns an immutable instance of the field container. */
toImmutable(B fields)43   abstract T toImmutable(B fields);
44 
45   /**
46    * Sets the unknown fields into the message. Caller must take care of the mutability of the
47    * fields.
48    */
setToMessage(Object message, T fields)49   abstract void setToMessage(Object message, T fields);
50 
51   /** Get the unknown fields from the message. */
getFromMessage(Object message)52   abstract T getFromMessage(Object message);
53 
54   /** Returns a builder for unknown fields in the message. */
getBuilderFromMessage(Object message)55   abstract B getBuilderFromMessage(Object message);
56 
57   /** Sets an unknown field builder into the message. */
setBuilderToMessage(Object message, B builder)58   abstract void setBuilderToMessage(Object message, B builder);
59 
60   /** Marks unknown fields as immutable. */
makeImmutable(Object message)61   abstract void makeImmutable(Object message);
62 
63   /** Merges one field into the unknown fields. */
mergeOneFieldFrom(B unknownFields, Reader reader, int currentDepth)64   final boolean mergeOneFieldFrom(B unknownFields, Reader reader, int currentDepth)
65       throws IOException {
66     int tag = reader.getTag();
67     int fieldNumber = WireFormat.getTagFieldNumber(tag);
68     switch (WireFormat.getTagWireType(tag)) {
69       case WireFormat.WIRETYPE_VARINT:
70         addVarint(unknownFields, fieldNumber, reader.readInt64());
71         return true;
72       case WireFormat.WIRETYPE_FIXED32:
73         addFixed32(unknownFields, fieldNumber, reader.readFixed32());
74         return true;
75       case WireFormat.WIRETYPE_FIXED64:
76         addFixed64(unknownFields, fieldNumber, reader.readFixed64());
77         return true;
78       case WireFormat.WIRETYPE_LENGTH_DELIMITED:
79         addLengthDelimited(unknownFields, fieldNumber, reader.readBytes());
80         return true;
81       case WireFormat.WIRETYPE_START_GROUP:
82         final B subFields = newBuilder();
83         int endGroupTag = WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
84         currentDepth++;
85         if (currentDepth >= recursionLimit) {
86           throw InvalidProtocolBufferException.recursionLimitExceeded();
87         }
88         mergeFrom(subFields, reader, currentDepth);
89         currentDepth--;
90         if (endGroupTag != reader.getTag()) {
91           throw InvalidProtocolBufferException.invalidEndTag();
92         }
93         addGroup(unknownFields, fieldNumber, toImmutable(subFields));
94         return true;
95       case WireFormat.WIRETYPE_END_GROUP:
96         return false;
97       default:
98         throw InvalidProtocolBufferException.invalidWireType();
99     }
100   }
101 
mergeFrom(B unknownFields, Reader reader, int currentDepth)102   private final void mergeFrom(B unknownFields, Reader reader, int currentDepth)
103       throws IOException {
104     while (true) {
105       if (reader.getFieldNumber() == Reader.READ_DONE
106           || !mergeOneFieldFrom(unknownFields, reader, currentDepth)) {
107         break;
108       }
109     }
110   }
111 
writeTo(T unknownFields, Writer writer)112   abstract void writeTo(T unknownFields, Writer writer) throws IOException;
113 
writeAsMessageSetTo(T unknownFields, Writer writer)114   abstract void writeAsMessageSetTo(T unknownFields, Writer writer) throws IOException;
115 
116   /** Merges {@code source} into {@code destination} and returns the merged instance. */
merge(T destination, T source)117   abstract T merge(T destination, T source);
118 
119   /** Get the serialized size for message set serialization. */
getSerializedSizeAsMessageSet(T message)120   abstract int getSerializedSizeAsMessageSet(T message);
121 
getSerializedSize(T unknowns)122   abstract int getSerializedSize(T unknowns);
123 
124   /**
125    * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if
126    * the depth of the message exceeds this limit.
127    */
setRecursionLimit(int limit)128   public void setRecursionLimit(int limit) {
129     recursionLimit = limit;
130   }
131 }
132