Home | History | Annotate | Download | only in nano
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2013 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.nano;
     32 
     33 import java.io.IOException;
     34 
     35 /**
     36  * Reads and decodes protocol message fields.
     37  *
     38  * This class contains two kinds of methods:  methods that read specific
     39  * protocol message constructs and field types (e.g. {@link #readTag()} and
     40  * {@link #readInt32()}) and methods that read low-level values (e.g.
     41  * {@link #readRawVarint32()} and {@link #readRawBytes}).  If you are reading
     42  * encoded protocol messages, you should use the former methods, but if you are
     43  * reading some other format of your own design, use the latter.
     44  *
     45  * @author kenton (at) google.com Kenton Varda
     46  */
     47 public final class CodedInputByteBufferNano {
     48   /**
     49    * Create a new CodedInputStream wrapping the given byte array.
     50    */
     51   public static CodedInputByteBufferNano newInstance(final byte[] buf) {
     52     return newInstance(buf, 0, buf.length);
     53   }
     54 
     55   /**
     56    * Create a new CodedInputStream wrapping the given byte array slice.
     57    */
     58   public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off,
     59                                              final int len) {
     60     return new CodedInputByteBufferNano(buf, off, len);
     61   }
     62 
     63   // -----------------------------------------------------------------
     64 
     65   /**
     66    * Attempt to read a field tag, returning zero if we have reached EOF.
     67    * Protocol message parsers use this to read tags, since a protocol message
     68    * may legally end wherever a tag occurs, and zero is not a valid tag number.
     69    */
     70   public int readTag() throws IOException {
     71     if (isAtEnd()) {
     72       lastTag = 0;
     73       return 0;
     74     }
     75 
     76     lastTag = readRawVarint32();
     77     if (lastTag == 0) {
     78       // If we actually read zero, that's not a valid tag.
     79       throw InvalidProtocolBufferNanoException.invalidTag();
     80     }
     81     return lastTag;
     82   }
     83 
     84   /**
     85    * Verifies that the last call to readTag() returned the given tag value.
     86    * This is used to verify that a nested group ended with the correct
     87    * end tag.
     88    *
     89    * @throws InvalidProtocolBufferNanoException {@code value} does not match the
     90    *                                        last tag.
     91    */
     92   public void checkLastTagWas(final int value)
     93                               throws InvalidProtocolBufferNanoException {
     94     if (lastTag != value) {
     95       throw InvalidProtocolBufferNanoException.invalidEndTag();
     96     }
     97   }
     98 
     99   /**
    100    * Reads and discards a single field, given its tag value.
    101    *
    102    * @return {@code false} if the tag is an endgroup tag, in which case
    103    *         nothing is skipped.  Otherwise, returns {@code true}.
    104    */
    105   public boolean skipField(final int tag) throws IOException {
    106     switch (WireFormatNano.getTagWireType(tag)) {
    107       case WireFormatNano.WIRETYPE_VARINT:
    108         readInt32();
    109         return true;
    110       case WireFormatNano.WIRETYPE_FIXED64:
    111         readRawLittleEndian64();
    112         return true;
    113       case WireFormatNano.WIRETYPE_LENGTH_DELIMITED:
    114         skipRawBytes(readRawVarint32());
    115         return true;
    116       case WireFormatNano.WIRETYPE_START_GROUP:
    117         skipMessage();
    118         checkLastTagWas(
    119           WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag),
    120                              WireFormatNano.WIRETYPE_END_GROUP));
    121         return true;
    122       case WireFormatNano.WIRETYPE_END_GROUP:
    123         return false;
    124       case WireFormatNano.WIRETYPE_FIXED32:
    125         readRawLittleEndian32();
    126         return true;
    127       default:
    128         throw InvalidProtocolBufferNanoException.invalidWireType();
    129     }
    130   }
    131 
    132   /**
    133    * Reads and discards an entire message.  This will read either until EOF
    134    * or until an endgroup tag, whichever comes first.
    135    */
    136   public void skipMessage() throws IOException {
    137     while (true) {
    138       final int tag = readTag();
    139       if (tag == 0 || !skipField(tag)) {
    140         return;
    141       }
    142     }
    143   }
    144 
    145   // -----------------------------------------------------------------
    146 
    147   /** Read a {@code double} field value from the stream. */
    148   public double readDouble() throws IOException {
    149     return Double.longBitsToDouble(readRawLittleEndian64());
    150   }
    151 
    152   /** Read a {@code float} field value from the stream. */
    153   public float readFloat() throws IOException {
    154     return Float.intBitsToFloat(readRawLittleEndian32());
    155   }
    156 
    157   /** Read a {@code uint64} field value from the stream. */
    158   public long readUInt64() throws IOException {
    159     return readRawVarint64();
    160   }
    161 
    162   /** Read an {@code int64} field value from the stream. */
    163   public long readInt64() throws IOException {
    164     return readRawVarint64();
    165   }
    166 
    167   /** Read an {@code int32} field value from the stream. */
    168   public int readInt32() throws IOException {
    169     return readRawVarint32();
    170   }
    171 
    172   /** Read a {@code fixed64} field value from the stream. */
    173   public long readFixed64() throws IOException {
    174     return readRawLittleEndian64();
    175   }
    176 
    177   /** Read a {@code fixed32} field value from the stream. */
    178   public int readFixed32() throws IOException {
    179     return readRawLittleEndian32();
    180   }
    181 
    182   /** Read a {@code bool} field value from the stream. */
    183   public boolean readBool() throws IOException {
    184     return readRawVarint32() != 0;
    185   }
    186 
    187   /** Read a {@code string} field value from the stream. */
    188   public String readString() throws IOException {
    189     final int size = readRawVarint32();
    190     if (size <= (bufferSize - bufferPos) && size > 0) {
    191       // Fast path:  We already have the bytes in a contiguous buffer, so
    192       //   just copy directly from it.
    193       final String result = new String(buffer, bufferPos, size, InternalNano.UTF_8);
    194       bufferPos += size;
    195       return result;
    196     } else {
    197       // Slow path:  Build a byte array first then copy it.
    198       return new String(readRawBytes(size), InternalNano.UTF_8);
    199     }
    200   }
    201 
    202   /** Read a {@code group} field value from the stream. */
    203   public void readGroup(final MessageNano msg, final int fieldNumber)
    204       throws IOException {
    205     if (recursionDepth >= recursionLimit) {
    206       throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
    207     }
    208     ++recursionDepth;
    209     msg.mergeFrom(this);
    210     checkLastTagWas(
    211       WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP));
    212     --recursionDepth;
    213   }
    214 
    215   public void readMessage(final MessageNano msg)
    216       throws IOException {
    217     final int length = readRawVarint32();
    218     if (recursionDepth >= recursionLimit) {
    219       throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
    220     }
    221     final int oldLimit = pushLimit(length);
    222     ++recursionDepth;
    223     msg.mergeFrom(this);
    224     checkLastTagWas(0);
    225     --recursionDepth;
    226     popLimit(oldLimit);
    227   }
    228 
    229   /** Read a {@code bytes} field value from the stream. */
    230   public byte[] readBytes() throws IOException {
    231     final int size = readRawVarint32();
    232     if (size <= (bufferSize - bufferPos) && size > 0) {
    233       // Fast path:  We already have the bytes in a contiguous buffer, so
    234       //   just copy directly from it.
    235       final byte[] result = new byte[size];
    236       System.arraycopy(buffer, bufferPos, result, 0, size);
    237       bufferPos += size;
    238       return result;
    239     } else if (size == 0) {
    240       return WireFormatNano.EMPTY_BYTES;
    241     } else {
    242       // Slow path:  Build a byte array first then copy it.
    243       return readRawBytes(size);
    244     }
    245   }
    246 
    247   /** Read a {@code uint32} field value from the stream. */
    248   public int readUInt32() throws IOException {
    249     return readRawVarint32();
    250   }
    251 
    252   /**
    253    * Read an enum field value from the stream.  Caller is responsible
    254    * for converting the numeric value to an actual enum.
    255    */
    256   public int readEnum() throws IOException {
    257     return readRawVarint32();
    258   }
    259 
    260   /** Read an {@code sfixed32} field value from the stream. */
    261   public int readSFixed32() throws IOException {
    262     return readRawLittleEndian32();
    263   }
    264 
    265   /** Read an {@code sfixed64} field value from the stream. */
    266   public long readSFixed64() throws IOException {
    267     return readRawLittleEndian64();
    268   }
    269 
    270   /** Read an {@code sint32} field value from the stream. */
    271   public int readSInt32() throws IOException {
    272     return decodeZigZag32(readRawVarint32());
    273   }
    274 
    275   /** Read an {@code sint64} field value from the stream. */
    276   public long readSInt64() throws IOException {
    277     return decodeZigZag64(readRawVarint64());
    278   }
    279 
    280   // =================================================================
    281 
    282   /**
    283    * Read a raw Varint from the stream.  If larger than 32 bits, discard the
    284    * upper bits.
    285    */
    286   public int readRawVarint32() throws IOException {
    287     byte tmp = readRawByte();
    288     if (tmp >= 0) {
    289       return tmp;
    290     }
    291     int result = tmp & 0x7f;
    292     if ((tmp = readRawByte()) >= 0) {
    293       result |= tmp << 7;
    294     } else {
    295       result |= (tmp & 0x7f) << 7;
    296       if ((tmp = readRawByte()) >= 0) {
    297         result |= tmp << 14;
    298       } else {
    299         result |= (tmp & 0x7f) << 14;
    300         if ((tmp = readRawByte()) >= 0) {
    301           result |= tmp << 21;
    302         } else {
    303           result |= (tmp & 0x7f) << 21;
    304           result |= (tmp = readRawByte()) << 28;
    305           if (tmp < 0) {
    306             // Discard upper 32 bits.
    307             for (int i = 0; i < 5; i++) {
    308               if (readRawByte() >= 0) {
    309                 return result;
    310               }
    311             }
    312             throw InvalidProtocolBufferNanoException.malformedVarint();
    313           }
    314         }
    315       }
    316     }
    317     return result;
    318   }
    319 
    320   /** Read a raw Varint from the stream. */
    321   public long readRawVarint64() throws IOException {
    322     int shift = 0;
    323     long result = 0;
    324     while (shift < 64) {
    325       final byte b = readRawByte();
    326       result |= (long)(b & 0x7F) << shift;
    327       if ((b & 0x80) == 0) {
    328         return result;
    329       }
    330       shift += 7;
    331     }
    332     throw InvalidProtocolBufferNanoException.malformedVarint();
    333   }
    334 
    335   /** Read a 32-bit little-endian integer from the stream. */
    336   public int readRawLittleEndian32() throws IOException {
    337     final byte b1 = readRawByte();
    338     final byte b2 = readRawByte();
    339     final byte b3 = readRawByte();
    340     final byte b4 = readRawByte();
    341     return ((b1 & 0xff)      ) |
    342            ((b2 & 0xff) <<  8) |
    343            ((b3 & 0xff) << 16) |
    344            ((b4 & 0xff) << 24);
    345   }
    346 
    347   /** Read a 64-bit little-endian integer from the stream. */
    348   public long readRawLittleEndian64() throws IOException {
    349     final byte b1 = readRawByte();
    350     final byte b2 = readRawByte();
    351     final byte b3 = readRawByte();
    352     final byte b4 = readRawByte();
    353     final byte b5 = readRawByte();
    354     final byte b6 = readRawByte();
    355     final byte b7 = readRawByte();
    356     final byte b8 = readRawByte();
    357     return (((long)b1 & 0xff)      ) |
    358            (((long)b2 & 0xff) <<  8) |
    359            (((long)b3 & 0xff) << 16) |
    360            (((long)b4 & 0xff) << 24) |
    361            (((long)b5 & 0xff) << 32) |
    362            (((long)b6 & 0xff) << 40) |
    363            (((long)b7 & 0xff) << 48) |
    364            (((long)b8 & 0xff) << 56);
    365   }
    366 
    367   /**
    368    * Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
    369    * into values that can be efficiently encoded with varint.  (Otherwise,
    370    * negative values must be sign-extended to 64 bits to be varint encoded,
    371    * thus always taking 10 bytes on the wire.)
    372    *
    373    * @param n An unsigned 32-bit integer, stored in a signed int because
    374    *          Java has no explicit unsigned support.
    375    * @return A signed 32-bit integer.
    376    */
    377   public static int decodeZigZag32(final int n) {
    378     return (n >>> 1) ^ -(n & 1);
    379   }
    380 
    381   /**
    382    * Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
    383    * into values that can be efficiently encoded with varint.  (Otherwise,
    384    * negative values must be sign-extended to 64 bits to be varint encoded,
    385    * thus always taking 10 bytes on the wire.)
    386    *
    387    * @param n An unsigned 64-bit integer, stored in a signed int because
    388    *          Java has no explicit unsigned support.
    389    * @return A signed 64-bit integer.
    390    */
    391   public static long decodeZigZag64(final long n) {
    392     return (n >>> 1) ^ -(n & 1);
    393   }
    394 
    395   // -----------------------------------------------------------------
    396 
    397   private final byte[] buffer;
    398   private int bufferStart;
    399   private int bufferSize;
    400   private int bufferSizeAfterLimit;
    401   private int bufferPos;
    402   private int lastTag;
    403 
    404   /** The absolute position of the end of the current message. */
    405   private int currentLimit = Integer.MAX_VALUE;
    406 
    407   /** See setRecursionLimit() */
    408   private int recursionDepth;
    409   private int recursionLimit = DEFAULT_RECURSION_LIMIT;
    410 
    411   /** See setSizeLimit() */
    412   private int sizeLimit = DEFAULT_SIZE_LIMIT;
    413 
    414   private static final int DEFAULT_RECURSION_LIMIT = 64;
    415   private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
    416 
    417   private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) {
    418     this.buffer = buffer;
    419     bufferStart = off;
    420     bufferSize = off + len;
    421     bufferPos = off;
    422   }
    423 
    424   /**
    425    * Set the maximum message recursion depth.  In order to prevent malicious
    426    * messages from causing stack overflows, {@code CodedInputStream} limits
    427    * how deeply messages may be nested.  The default limit is 64.
    428    *
    429    * @return the old limit.
    430    */
    431   public int setRecursionLimit(final int limit) {
    432     if (limit < 0) {
    433       throw new IllegalArgumentException(
    434         "Recursion limit cannot be negative: " + limit);
    435     }
    436     final int oldLimit = recursionLimit;
    437     recursionLimit = limit;
    438     return oldLimit;
    439   }
    440 
    441   /**
    442    * Set the maximum message size.  In order to prevent malicious
    443    * messages from exhausting memory or causing integer overflows,
    444    * {@code CodedInputStream} limits how large a message may be.
    445    * The default limit is 64MB.  You should set this limit as small
    446    * as you can without harming your app's functionality.  Note that
    447    * size limits only apply when reading from an {@code InputStream}, not
    448    * when constructed around a raw byte array.
    449    * <p>
    450    * If you want to read several messages from a single CodedInputStream, you
    451    * could call {@link #resetSizeCounter()} after each one to avoid hitting the
    452    * size limit.
    453    *
    454    * @return the old limit.
    455    */
    456   public int setSizeLimit(final int limit) {
    457     if (limit < 0) {
    458       throw new IllegalArgumentException(
    459         "Size limit cannot be negative: " + limit);
    460     }
    461     final int oldLimit = sizeLimit;
    462     sizeLimit = limit;
    463     return oldLimit;
    464   }
    465 
    466   /**
    467    * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
    468    */
    469   public void resetSizeCounter() {
    470   }
    471 
    472   /**
    473    * Sets {@code currentLimit} to (current position) + {@code byteLimit}.  This
    474    * is called when descending into a length-delimited embedded message.
    475    *
    476    * @return the old limit.
    477    */
    478   public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException {
    479     if (byteLimit < 0) {
    480       throw InvalidProtocolBufferNanoException.negativeSize();
    481     }
    482     byteLimit += bufferPos;
    483     final int oldLimit = currentLimit;
    484     if (byteLimit > oldLimit) {
    485       throw InvalidProtocolBufferNanoException.truncatedMessage();
    486     }
    487     currentLimit = byteLimit;
    488 
    489     recomputeBufferSizeAfterLimit();
    490 
    491     return oldLimit;
    492   }
    493 
    494   private void recomputeBufferSizeAfterLimit() {
    495     bufferSize += bufferSizeAfterLimit;
    496     final int bufferEnd = bufferSize;
    497     if (bufferEnd > currentLimit) {
    498       // Limit is in current buffer.
    499       bufferSizeAfterLimit = bufferEnd - currentLimit;
    500       bufferSize -= bufferSizeAfterLimit;
    501     } else {
    502       bufferSizeAfterLimit = 0;
    503     }
    504   }
    505 
    506   /**
    507    * Discards the current limit, returning to the previous limit.
    508    *
    509    * @param oldLimit The old limit, as returned by {@code pushLimit}.
    510    */
    511   public void popLimit(final int oldLimit) {
    512     currentLimit = oldLimit;
    513     recomputeBufferSizeAfterLimit();
    514   }
    515 
    516   /**
    517    * Returns the number of bytes to be read before the current limit.
    518    * If no limit is set, returns -1.
    519    */
    520   public int getBytesUntilLimit() {
    521     if (currentLimit == Integer.MAX_VALUE) {
    522       return -1;
    523     }
    524 
    525     final int currentAbsolutePosition = bufferPos;
    526     return currentLimit - currentAbsolutePosition;
    527   }
    528 
    529   /**
    530    * Returns true if the stream has reached the end of the input.  This is the
    531    * case if either the end of the underlying input source has been reached or
    532    * if the stream has reached a limit created using {@link #pushLimit(int)}.
    533    */
    534   public boolean isAtEnd() {
    535     return bufferPos == bufferSize;
    536   }
    537 
    538   /**
    539    * Get current position in buffer relative to beginning offset.
    540    */
    541   public int getPosition() {
    542     return bufferPos - bufferStart;
    543   }
    544 
    545   /**
    546    * Get current (absolute) position in buffer.
    547    */
    548   public int getAbsolutePosition() {
    549     return bufferPos;
    550   }
    551 
    552   /**
    553    * Return the raw underlying data in the buffer, directly.
    554    */
    555   public byte[] getBuffer() {
    556     return buffer;
    557   }
    558 
    559   /**
    560    * Retrieves a subset of data in the buffer. The returned array is not backed by the original
    561    * buffer array.
    562    *
    563    * @param offset the position (relative to the buffer start position) to start at.
    564    * @param length the number of bytes to retrieve.
    565    */
    566   public byte[] getData(int offset, int length) {
    567     if (length == 0) {
    568       return WireFormatNano.EMPTY_BYTES;
    569     }
    570     byte[] copy = new byte[length];
    571     int start = bufferStart + offset;
    572     System.arraycopy(buffer, start, copy, 0, length);
    573     return copy;
    574   }
    575 
    576   /**
    577    * Rewind to previous position. Cannot go forward.
    578    */
    579   public void rewindToPosition(int position) {
    580     if (position > bufferPos - bufferStart) {
    581       throw new IllegalArgumentException(
    582               "Position " + position + " is beyond current " + (bufferPos - bufferStart));
    583     }
    584     if (position < 0) {
    585       throw new IllegalArgumentException("Bad position " + position);
    586     }
    587     bufferPos = bufferStart + position;
    588   }
    589 
    590   /**
    591    * Read one byte from the input.
    592    *
    593    * @throws InvalidProtocolBufferNanoException The end of the stream or the current
    594    *                                        limit was reached.
    595    */
    596   public byte readRawByte() throws IOException {
    597     if (bufferPos == bufferSize) {
    598       throw InvalidProtocolBufferNanoException.truncatedMessage();
    599     }
    600     return buffer[bufferPos++];
    601   }
    602 
    603   /**
    604    * Read a fixed size of bytes from the input.
    605    *
    606    * @throws InvalidProtocolBufferNanoException The end of the stream or the current
    607    *                                        limit was reached.
    608    */
    609   public byte[] readRawBytes(final int size) throws IOException {
    610     if (size < 0) {
    611       throw InvalidProtocolBufferNanoException.negativeSize();
    612     }
    613 
    614     if (bufferPos + size > currentLimit) {
    615       // Read to the end of the stream anyway.
    616       skipRawBytes(currentLimit - bufferPos);
    617       // Then fail.
    618       throw InvalidProtocolBufferNanoException.truncatedMessage();
    619     }
    620 
    621     if (size <= bufferSize - bufferPos) {
    622       // We have all the bytes we need already.
    623       final byte[] bytes = new byte[size];
    624       System.arraycopy(buffer, bufferPos, bytes, 0, size);
    625       bufferPos += size;
    626       return bytes;
    627     } else {
    628       throw InvalidProtocolBufferNanoException.truncatedMessage();
    629     }
    630   }
    631 
    632   /**
    633    * Reads and discards {@code size} bytes.
    634    *
    635    * @throws InvalidProtocolBufferNanoException The end of the stream or the current
    636    *                                        limit was reached.
    637    */
    638   public void skipRawBytes(final int size) throws IOException {
    639     if (size < 0) {
    640       throw InvalidProtocolBufferNanoException.negativeSize();
    641     }
    642 
    643     if (bufferPos + size > currentLimit) {
    644       // Read to the end of the stream anyway.
    645       skipRawBytes(currentLimit - bufferPos);
    646       // Then fail.
    647       throw InvalidProtocolBufferNanoException.truncatedMessage();
    648     }
    649 
    650     if (size <= bufferSize - bufferPos) {
    651       // We have all the bytes we need already.
    652       bufferPos += size;
    653     } else {
    654       throw InvalidProtocolBufferNanoException.truncatedMessage();
    655     }
    656   }
    657 
    658   // Read a primitive type.
    659   Object readPrimitiveField(int type) throws IOException {
    660     switch (type) {
    661       case InternalNano.TYPE_DOUBLE:
    662           return readDouble();
    663       case InternalNano.TYPE_FLOAT:
    664           return readFloat();
    665       case InternalNano.TYPE_INT64:
    666           return readInt64();
    667       case InternalNano.TYPE_UINT64:
    668           return readUInt64();
    669       case InternalNano.TYPE_INT32:
    670           return readInt32();
    671       case InternalNano.TYPE_FIXED64:
    672           return readFixed64();
    673       case InternalNano.TYPE_FIXED32:
    674           return readFixed32();
    675       case InternalNano.TYPE_BOOL:
    676           return readBool();
    677       case InternalNano.TYPE_STRING:
    678           return readString();
    679       case InternalNano.TYPE_BYTES:
    680           return readBytes();
    681       case InternalNano.TYPE_UINT32:
    682           return readUInt32();
    683       case InternalNano.TYPE_ENUM:
    684           return readEnum();
    685       case InternalNano.TYPE_SFIXED32:
    686           return readSFixed32();
    687       case InternalNano.TYPE_SFIXED64:
    688           return readSFixed64();
    689       case InternalNano.TYPE_SINT32:
    690           return readSInt32();
    691       case InternalNano.TYPE_SINT64:
    692           return readSInt64();
    693       default:
    694           throw new IllegalArgumentException("Unknown type " + type);
    695     }
    696   }
    697 }
    698