All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.msgpack.MsgPackInputStream Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.msgpack;

import static org.apache.juneau.msgpack.DataType.*;
import static org.apache.juneau.internal.IOUtils.*;

import java.io.*;

import org.apache.juneau.parser.*;

/**
 * Specialized input stream for parsing MessagePack streams.
 *
 * 
Notes:
*
    *
  • This class is not intended for external use. *
*/ public final class MsgPackInputStream extends InputStream { private final ParserPipe pipe; private final InputStream is; private DataType currentDataType; private long length; private int lastByte; private int extType; int pos = 0; // Data type quick-lookup table. private static final DataType[] TYPES = new DataType[] { /*0x0?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x1?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x2?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x3?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x4?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x5?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x6?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x7?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0x8?*/ MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP,MAP, /*0x9?*/ ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY,ARRAY, /*0xA?*/ STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING, /*0xB?*/ STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING, /*0xC?*/ NULL, INVALID, BOOLEAN, BOOLEAN, BIN, BIN, BIN, EXT, EXT, EXT, FLOAT, DOUBLE, INT, INT, LONG, LONG, /*0xD?*/ INT, INT, INT, LONG, EXT, EXT, EXT, EXT, EXT, STRING, STRING, STRING, ARRAY, ARRAY, MAP, MAP, /*0xE?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT, /*0xF?*/ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT }; /** * Constructor. * * @param pipe The parser input. * @throws Exception */ protected MsgPackInputStream(ParserPipe pipe) throws Exception { this.pipe = pipe; this.is = pipe.getInputStream(); } @Override /* InputStream */ public int read() throws IOException { int i = is.read(); if (i > 0) pos++; return i; } /** * Reads the data type flag from the stream. * *

* This is the byte that indicates what kind of data follows. */ DataType readDataType() throws IOException { int i = read(); if (i == -1) throw new IOException("Unexpected end of file found at position " + pos); currentDataType = TYPES[i]; switch (currentDataType) { case NULL: case FLOAT: { length = 4; break; } case DOUBLE: { length = 8; break; } case BOOLEAN: { lastByte = i; break; } case INT: { // positive fixnum stores 7-bit positive integer // +--------+ // |0XXXXXXX| // +--------+ // // negative fixnum stores 5-bit negative integer // +--------+ // |111YYYYY| // +--------+ // // * 0XXXXXXX is 8-bit unsigned integer // * 111YYYYY is 8-bit signed integer // // uint 8 stores a 8-bit unsigned integer // +--------+--------+ // | 0xcc |ZZZZZZZZ| // +--------+--------+ // // uint 16 stores a 16-bit big-endian unsigned integer // +--------+--------+--------+ // | 0xcd |ZZZZZZZZ|ZZZZZZZZ| // +--------+--------+--------+ // // uint 32 stores a 32-bit big-endian unsigned integer // +--------+--------+--------+--------+--------+ // | 0xce |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| // +--------+--------+--------+--------+--------+ // // uint 64 stores a 64-bit big-endian unsigned integer // +--------+--------+--------+--------+--------+--------+--------+--------+--------+ // | 0xcf |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| // +--------+--------+--------+--------+--------+--------+--------+--------+--------+ // // int 8 stores a 8-bit signed integer // +--------+--------+ // | 0xd0 |ZZZZZZZZ| // +--------+--------+ // // int 16 stores a 16-bit big-endian signed integer // +--------+--------+--------+ // | 0xd1 |ZZZZZZZZ|ZZZZZZZZ| // +--------+--------+--------+ // // int 32 stores a 32-bit big-endian signed integer // +--------+--------+--------+--------+--------+ // | 0xd2 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| // +--------+--------+--------+--------+--------+ // // int 64 stores a 64-bit big-endian signed integer // +--------+--------+--------+--------+--------+--------+--------+--------+--------+ // | 0xd3 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| // +--------+--------+--------+--------+--------+--------+--------+--------+--------+ lastByte = i; if (i <= POSFIXINT_U) length = 0; else if (i >= NEGFIXINT_L) length = -1; else if (i == INT8 || i == UINT8) length = 1; else if (i == INT16 || i == UINT16) length = 2; else if (i == INT32) length = 4; else length = 0; break; } case LONG: { if (i == UINT32) length = 4; else if (i == INT64 || i == UINT64) length = 8; else length = 0; break; } case STRING:{ // fixstr stores a byte array whose length is up to 31 bytes: // +--------+========+ // |101XXXXX| data | // +--------+========+ // // str 8 stores a byte array whose length is up to (2^8)-1 bytes: // +--------+--------+========+ // | 0xd9 |YYYYYYYY| data | // +--------+--------+========+ // // str 16 stores a byte array whose length is up to (2^16)-1 bytes: // +--------+--------+--------+========+ // | 0xda |ZZZZZZZZ|ZZZZZZZZ| data | // +--------+--------+--------+========+ // // str 32 stores a byte array whose length is up to (2^32)-1 bytes: // +--------+--------+--------+--------+--------+========+ // | 0xdb |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA| data | // +--------+--------+--------+--------+--------+========+ // // where // * XXXXX is a 5-bit unsigned integer which represents N // * YYYYYYYY is a 8-bit unsigned integer which represents N // * ZZZZZZZZ_ZZZZZZZZ is a 16-bit big-endian unsigned integer which represents N // * AAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA is a 32-bit big-endian unsigned integer which represents N // * N is the length of data if (i <= FIXSTR_U) length = i & 0x1F; else if (i == STR8) length = readUInt1(); else if (i == STR16) length = readUInt2(); else length = readUInt4(); break; } case ARRAY: { // fixarray stores an array whose length is up to 15 elements: // +--------+~~~~~~~~~~~~~~~~~+ // |1001XXXX| N objects | // +--------+~~~~~~~~~~~~~~~~~+ // // array 16 stores an array whose length is up to (2^16)-1 elements: // +--------+--------+--------+~~~~~~~~~~~~~~~~~+ // | 0xdc |YYYYYYYY|YYYYYYYY| N objects | // +--------+--------+--------+~~~~~~~~~~~~~~~~~+ // // array 32 stores an array whose length is up to (2^32)-1 elements: // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+ // | 0xdd |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N objects | // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+ // // where // * XXXX is a 4-bit unsigned integer which represents N // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N // N is the size of a array if (i <= FIXARRAY_U) length = i & 0x0F; else if (i == ARRAY16) length = readUInt2(); else length = readUInt4(); break; } case BIN:{ // bin 8 stores a byte array whose length is up to (2^8)-1 bytes: // +--------+--------+========+ // | 0xc4 |XXXXXXXX| data | // +--------+--------+========+ // // bin 16 stores a byte array whose length is up to (2^16)-1 bytes: // +--------+--------+--------+========+ // | 0xc5 |YYYYYYYY|YYYYYYYY| data | // +--------+--------+--------+========+ // // bin 32 stores a byte array whose length is up to (2^32)-1 bytes: // +--------+--------+--------+--------+--------+========+ // | 0xc6 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| data | // +--------+--------+--------+--------+--------+========+ // // where // * XXXXXXXX is a 8-bit unsigned integer which represents N // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N // * N is the length of data if (i == BIN8) length = readUInt1(); else if (i == BIN16) length = readUInt2(); else length = readUInt4(); break; } case EXT:{ // fixext 1 stores an integer and a byte array whose length is 1 byte // +--------+--------+--------+ // | 0xd4 | type | data | // +--------+--------+--------+ // // fixext 2 stores an integer and a byte array whose length is 2 bytes // +--------+--------+--------+--------+ // | 0xd5 | type | data | // +--------+--------+--------+--------+ // // fixext 4 stores an integer and a byte array whose length is 4 bytes // +--------+--------+--------+--------+--------+--------+ // | 0xd6 | type | data | // +--------+--------+--------+--------+--------+--------+ // // fixext 8 stores an integer and a byte array whose length is 8 bytes // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ // | 0xd7 | type | data | // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ // // fixext 16 stores an integer and a byte array whose length is 16 bytes // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ // | 0xd8 | type | data // +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ // +--------+--------+--------+--------+--------+--------+--------+--------+ // data (cont.) | // +--------+--------+--------+--------+--------+--------+--------+--------+ // // ext 8 stores an integer and a byte array whose length is up to (2^8)-1 bytes: // +--------+--------+--------+========+ // | 0xc7 |XXXXXXXX| type | data | // +--------+--------+--------+========+ // // ext 16 stores an integer and a byte array whose length is up to (2^16)-1 bytes: // +--------+--------+--------+--------+========+ // | 0xc8 |YYYYYYYY|YYYYYYYY| type | data | // +--------+--------+--------+--------+========+ // // ext 32 stores an integer and a byte array whose length is up to (2^32)-1 bytes: // +--------+--------+--------+--------+--------+--------+========+ // | 0xc9 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| type | data | // +--------+--------+--------+--------+--------+--------+========+ // // where // * XXXXXXXX is a 8-bit unsigned integer which represents N // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a big-endian 32-bit unsigned integer which represents N // * N is a length of data // * type is a signed 8-bit signed integer // * type < 0 is reserved for future extension including 2-byte type information if (i == FIXEXT1) length = 1; else if (i == FIXEXT2) length = 2; else if (i == FIXEXT4) length = 4; else if (i == FIXEXT8) length = 8; else if (i == FIXEXT16) length = 16; else if (i == EXT8) length = readUInt1(); else if (i == EXT16) length = readUInt2(); else if (i == EXT32) length = readUInt4(); extType = is.read(); break; } case MAP:{ // fixmap stores a map whose length is up to 15 elements // +--------+~~~~~~~~~~~~~~~~~+ // |1000XXXX| N*2 objects | // +--------+~~~~~~~~~~~~~~~~~+ // // map 16 stores a map whose length is up to (2^16)-1 elements // +--------+--------+--------+~~~~~~~~~~~~~~~~~+ // | 0xde |YYYYYYYY|YYYYYYYY| N*2 objects | // +--------+--------+--------+~~~~~~~~~~~~~~~~~+ // // map 32 stores a map whose length is up to (2^32)-1 elements // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+ // | 0xdf |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N*2 objects | // +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+ // // where // * XXXX is a 4-bit unsigned integer which represents N // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N // * N is the size of a map // * odd elements in objects are keys of a map // * the next element of a key is its associated value if (i <= FIXMAP_U) length = i & 0x0F; else if (i == MAP16) length = readUInt2(); else length = readUInt4(); break; } default: throw new IOException("Invalid flag 0xC1 detected in stream."); } return currentDataType; } /** * Returns the length value for the field. * *

* For ints/floats/bins/strings, this is the number of bytes that the field takes up (minus the data-type flag). * For arrays, it's the number of array entries. * For maps, it's the number of map entries. */ long readLength() { return length; } /** * Read a boolean from the stream. */ boolean readBoolean() { return lastByte == TRUE; } /** * Read a string from the stream. */ String readString() throws IOException { return new String(readBinary(), UTF8); } /** * Read a binary field from the stream. */ byte[] readBinary() throws IOException { byte[] b = new byte[(int)length]; is.read(b); return b; } /** * Read an integer from the stream. */ int readInt() throws IOException { if (length == 0) return lastByte; if (length == 1) return is.read(); if (length == 2) return (is.read() << 8) | is.read(); int i = is.read(); i <<= 8; i |= is.read(); i <<= 8; i |= is.read(); i <<= 8; i |= is.read(); return i; } /** * Read a float from the stream. */ float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } /** * Read a double from the stream. */ double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); } /** * Read 64-bit long from the stream. */ long readLong() throws IOException { if (length == 4) return readUInt4(); long l = is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); return l; } /** * Return the extended-format type. * Currently not used. */ int getExtType() { return extType; } /** * Read one byte from the stream. */ private int readUInt1() throws IOException { return is.read(); } /** * Read two bytes from the stream. */ private int readUInt2() throws IOException { return (is.read() << 8) | is.read(); } /** * Read four bytes from the stream. */ private long readUInt4() throws IOException { long l = is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); l <<= 8; l |= is.read(); return l; } /** * Return the current read position in the stream (i.e. number of bytes we've read so far). */ int getPosition() { return pos; } /** * Returns the pipe that was passed into the constructor. * * @return The pipe that was passed into the constructor. */ public ParserPipe getPipe() { return pipe; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy