• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 java.io.IOException;
34 
35 /**
36  * Implements the lite version of map entry messages.
37  *
38  * This class serves as an utility class to help do serialization/parsing of
39  * map entries. It's used in generated code and also in the full version
40  * MapEntry message.
41  *
42  * Protobuf internal. Users shouldn't use.
43  */
44 public class MapEntryLite<K, V>
45     extends AbstractMessageLite<MapEntryLite<K, V>, MapEntryLite.Builder<K, V>> {
46   private static class Metadata<K, V> {
47     public final MapEntryLite<K, V> defaultInstance;
48     public final WireFormat.FieldType keyType;
49     public final WireFormat.FieldType valueType;
50     public final Parser<MapEntryLite<K, V>> parser;
Metadata( MapEntryLite<K, V> defaultInstance, WireFormat.FieldType keyType, WireFormat.FieldType valueType)51     public Metadata(
52         MapEntryLite<K, V> defaultInstance,
53         WireFormat.FieldType keyType,
54         WireFormat.FieldType valueType) {
55       this.defaultInstance = defaultInstance;
56       this.keyType = keyType;
57       this.valueType = valueType;
58       final Metadata<K, V> finalThis = this;
59       this.parser = new AbstractParser<MapEntryLite<K, V>>() {
60         @Override
61         public MapEntryLite<K, V> parsePartialFrom(
62             CodedInputStream input, ExtensionRegistryLite extensionRegistry)
63             throws InvalidProtocolBufferException {
64           return new MapEntryLite<K, V>(finalThis, input, extensionRegistry);
65         }
66       };
67     }
68   }
69 
70   private static final int KEY_FIELD_NUMBER = 1;
71   private static final int VALUE_FIELD_NUMBER = 2;
72 
73   private final Metadata<K, V> metadata;
74   private final K key;
75   private final V value;
76 
77   /** Creates a default MapEntryLite message instance. */
MapEntryLite( WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue)78   private MapEntryLite(
79       WireFormat.FieldType keyType, K defaultKey,
80       WireFormat.FieldType valueType, V defaultValue) {
81     this.metadata = new Metadata<K, V>(this, keyType, valueType);
82     this.key = defaultKey;
83     this.value = defaultValue;
84   }
85 
86   /** Creates a new MapEntryLite message. */
MapEntryLite(Metadata<K, V> metadata, K key, V value)87   private MapEntryLite(Metadata<K, V> metadata, K key, V value) {
88     this.metadata = metadata;
89     this.key = key;
90     this.value = value;
91   }
92 
getKey()93   public K getKey() {
94     return key;
95   }
96 
getValue()97   public V getValue() {
98     return value;
99   }
100 
101   /**
102    * Creates a default MapEntryLite message instance.
103    *
104    * This method is used by generated code to create the default instance for
105    * a map entry message. The created default instance should be used to create
106    * new map entry messages of the same type. For each map entry message, only
107    * one default instance should be created.
108    */
newDefaultInstance( WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue)109   public static <K, V> MapEntryLite<K, V> newDefaultInstance(
110       WireFormat.FieldType keyType, K defaultKey,
111       WireFormat.FieldType valueType, V defaultValue) {
112     return new MapEntryLite<K, V>(
113         keyType, defaultKey, valueType, defaultValue);
114   }
115 
116   @Override
writeTo(CodedOutputStream output)117   public void writeTo(CodedOutputStream output) throws IOException {
118     writeField(KEY_FIELD_NUMBER, metadata.keyType, key, output);
119     writeField(VALUE_FIELD_NUMBER, metadata.valueType, value, output);
120   }
121 
writeField( int number, WireFormat.FieldType type, Object value, CodedOutputStream output)122   private void writeField(
123       int number, WireFormat.FieldType type, Object value,
124       CodedOutputStream output) throws IOException {
125     output.writeTag(number, type.getWireType());
126     FieldSet.writeElementNoTag(output, type, value);
127   }
128 
129   private volatile int cachedSerializedSize = -1;
130   @Override
getSerializedSize()131   public int getSerializedSize() {
132     if (cachedSerializedSize != -1) {
133       return cachedSerializedSize;
134     }
135     int size = 0;
136     size += getFieldSize(KEY_FIELD_NUMBER, metadata.keyType, key);
137     size += getFieldSize(VALUE_FIELD_NUMBER, metadata.valueType, value);
138     cachedSerializedSize = size;
139     return size;
140   }
141 
getFieldSize( int number, WireFormat.FieldType type, Object value)142   private int getFieldSize(
143       int number, WireFormat.FieldType type, Object value) {
144     return CodedOutputStream.computeTagSize(number)
145         + FieldSet.computeElementSizeNoTag(type, value);
146   }
147 
148   /** Parsing constructor. */
MapEntryLite( Metadata<K, V> metadata, CodedInputStream input, ExtensionRegistryLite extensionRegistry)149   private MapEntryLite(
150       Metadata<K, V> metadata,
151       CodedInputStream input,
152       ExtensionRegistryLite extensionRegistry)
153       throws InvalidProtocolBufferException {
154     try {
155       K key = metadata.defaultInstance.key;
156       V value = metadata.defaultInstance.value;
157       while (true) {
158         int tag = input.readTag();
159         if (tag == 0) {
160           break;
161         }
162         if (tag == WireFormat.makeTag(
163                 KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
164           key = mergeField(
165               input, extensionRegistry, metadata.keyType, key);
166         } else if (tag == WireFormat.makeTag(
167                        VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) {
168           value = mergeField(
169               input, extensionRegistry, metadata.valueType, value);
170         } else {
171           if (!input.skipField(tag)) {
172             break;
173           }
174         }
175       }
176       this.metadata = metadata;
177       this.key = key;
178       this.value = value;
179     } catch (InvalidProtocolBufferException e) {
180       throw e.setUnfinishedMessage(this);
181     } catch (IOException e) {
182       throw new InvalidProtocolBufferException(e.getMessage())
183           .setUnfinishedMessage(this);
184     }
185   }
186 
187   @SuppressWarnings("unchecked")
mergeField( CodedInputStream input, ExtensionRegistryLite extensionRegistry, WireFormat.FieldType type, T value)188   private <T> T mergeField(
189       CodedInputStream input, ExtensionRegistryLite extensionRegistry,
190       WireFormat.FieldType type, T value) throws IOException {
191     switch (type) {
192       case MESSAGE:
193         MessageLite.Builder subBuilder = ((MessageLite) value).toBuilder();
194         input.readMessage(subBuilder, extensionRegistry);
195         return (T) subBuilder.buildPartial();
196       case ENUM:
197         return (T) (java.lang.Integer) input.readEnum();
198       case GROUP:
199         throw new RuntimeException("Groups are not allowed in maps.");
200       default:
201         return (T) FieldSet.readPrimitiveField(input, type, true);
202     }
203   }
204 
205   @Override
getParserForType()206   public Parser<MapEntryLite<K, V>> getParserForType() {
207     return metadata.parser;
208   }
209 
210   @Override
newBuilderForType()211   public Builder<K, V> newBuilderForType() {
212     return new Builder<K, V>(metadata);
213   }
214 
215   @Override
toBuilder()216   public Builder<K, V> toBuilder() {
217     return new Builder<K, V>(metadata, key, value);
218   }
219 
220   @Override
getDefaultInstanceForType()221   public MapEntryLite<K, V> getDefaultInstanceForType() {
222     return metadata.defaultInstance;
223   }
224 
225   @Override
isInitialized()226   public boolean isInitialized() {
227     if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
228       return ((MessageLite) value).isInitialized();
229     }
230     return true;
231   }
232 
233   /**
234    * Builder used to create {@link MapEntryLite} messages.
235    */
236   public static class Builder<K, V>
237       extends AbstractMessageLite.Builder<MapEntryLite<K, V>, Builder<K, V>> {
238     private final Metadata<K, V> metadata;
239     private K key;
240     private V value;
241 
Builder(Metadata<K, V> metadata)242     private Builder(Metadata<K, V> metadata) {
243       this.metadata = metadata;
244       this.key = metadata.defaultInstance.key;
245       this.value = metadata.defaultInstance.value;
246     }
247 
getKey()248     public K getKey() {
249       return key;
250     }
251 
getValue()252     public V getValue() {
253       return value;
254     }
255 
setKey(K key)256     public Builder<K, V> setKey(K key) {
257       this.key = key;
258       return this;
259     }
260 
setValue(V value)261     public Builder<K, V> setValue(V value) {
262       this.value = value;
263       return this;
264     }
265 
clearKey()266     public Builder<K, V> clearKey() {
267       this.key = metadata.defaultInstance.key;
268       return this;
269     }
270 
clearValue()271     public Builder<K, V> clearValue() {
272       this.value = metadata.defaultInstance.value;
273       return this;
274     }
275 
276     @Override
clear()277     public Builder<K, V> clear() {
278       this.key = metadata.defaultInstance.key;
279       this.value = metadata.defaultInstance.value;
280       return this;
281     }
282 
283     @Override
build()284     public MapEntryLite<K, V> build() {
285       MapEntryLite<K, V> result = buildPartial();
286       if (!result.isInitialized()) {
287         throw newUninitializedMessageException(result);
288       }
289       return result;
290     }
291 
292     @Override
buildPartial()293     public MapEntryLite<K, V> buildPartial() {
294       return new MapEntryLite<K, V>(metadata, key, value);
295     }
296 
297     @Override
getDefaultInstanceForType()298     public MessageLite getDefaultInstanceForType() {
299       return metadata.defaultInstance;
300     }
301 
302     @Override
isInitialized()303     public boolean isInitialized() {
304       if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
305         return ((MessageLite) value).isInitialized();
306       }
307       return true;
308     }
309 
Builder(Metadata<K, V> metadata, K key, V value)310     private Builder(Metadata<K, V> metadata, K key, V value) {
311       this.metadata = metadata;
312       this.key = key;
313       this.value = value;
314     }
315 
316     @Override
clone()317     public Builder<K, V> clone() {
318       return new Builder<K, V>(metadata, key, value);
319     }
320 
321     @Override
mergeFrom( CodedInputStream input, ExtensionRegistryLite extensionRegistry)322     public Builder<K, V> mergeFrom(
323         CodedInputStream input, ExtensionRegistryLite extensionRegistry)
324         throws IOException {
325       MapEntryLite<K, V> entry =
326           new MapEntryLite<K, V>(metadata, input, extensionRegistry);
327       this.key = entry.key;
328       this.value = entry.value;
329       return this;
330     }
331 
332     @Override
internalMergeFrom(MapEntryLite<K, V> message)333     protected Builder<K, V> internalMergeFrom(MapEntryLite<K, V> message) {
334       throw new UnsupportedOperationException();
335     }
336   }
337 }
338