|
|
@@ -40,7 +40,7 @@ public final class ProtoBufUtil {
|
|
|
/**
|
|
|
* Get an int with "tag" from the proto buffer. If the given field can't be
|
|
|
* retrieved, return the provided default value.
|
|
|
- *
|
|
|
+ *
|
|
|
* @param proto The proto buffer.
|
|
|
* @param tag The tag value that identifies which protocol buffer field to
|
|
|
* retrieve.
|
|
|
@@ -110,14 +110,40 @@ public final class ProtoBufUtil {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns an input stream for reading protocol buffer
|
|
|
+ * responses. This method reads a 32-bit signed integer from the
|
|
|
+ * stream, which determines the data size and compression. If the
|
|
|
+ * integer is negative, indicating a GZipped input stream which we
|
|
|
+ * do not support, an exception is thrown. Otherwise, just a
|
|
|
+ * BoundInputStream is returned. The input stream returned is always
|
|
|
+ * limited to the data available.
|
|
|
+ *
|
|
|
+ * @param dataInput the data input to read from
|
|
|
+ * @return an input stream, limited to the data size read from the stream
|
|
|
+ * @throws IOException if the incoming stream is gzipped.
|
|
|
+ */
|
|
|
+ public static InputStream getInputStreamForProtoBufResponse(
|
|
|
+ DataInput dataInput) throws IOException {
|
|
|
+
|
|
|
+ int size = dataInput.readInt();
|
|
|
+ InputStream is = new BoundInputStream((InputStream) dataInput,
|
|
|
+ Math.abs(size));
|
|
|
+
|
|
|
+ if (size < 0) {
|
|
|
+ throw new IOException("Cannot read gzipped streams");
|
|
|
+ }
|
|
|
+ return is;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Reads a single protocol buffer from the given input stream. This method is
|
|
|
- * provided where the client needs incremental access to the contents of a
|
|
|
- * protocol buffer which contains a sequence of protocol buffers.
|
|
|
+ * provided where the client needs incremental access to the contents of a
|
|
|
+ * protocol buffer which contains a sequence of protocol buffers.
|
|
|
* <p />
|
|
|
- * Please use {@link #getInputStreamForProtoBufResponse} to obtain an input
|
|
|
+ * Please use {@link #getInputStreamForProtoBufResponse} to obtain an input
|
|
|
* stream suitable for this method.
|
|
|
- *
|
|
|
+ *
|
|
|
* @param umbrellaType the type of the "outer" protocol buffer containing
|
|
|
* the message to read
|
|
|
* @param is the stream to read the protocol buffer from
|
|
|
@@ -125,24 +151,46 @@ public final class ProtoBufUtil {
|
|
|
* with the data read and the type will be set)
|
|
|
* @return the tag id of the message, -1 at the end of the stream
|
|
|
*/
|
|
|
- public static int readNextProtoBuf(ProtoBufType umbrellaType,
|
|
|
+ public static int readNextProtoBuf(ProtoBufType umbrellaType,
|
|
|
InputStream is, ProtoBuf result) throws IOException {
|
|
|
long tagAndType = ProtoBuf.readVarInt(is, true /* permits EOF */);
|
|
|
if (tagAndType == -1) {
|
|
|
return -1;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if ((tagAndType & 7) != ProtoBuf.WIRETYPE_LENGTH_DELIMITED) {
|
|
|
throw new IOException("Message expected");
|
|
|
}
|
|
|
int tag = (int) (tagAndType >>> 3);
|
|
|
-
|
|
|
+
|
|
|
result.setType((ProtoBufType) umbrellaType.getData(tag));
|
|
|
int length = (int) ProtoBuf.readVarInt(is, false);
|
|
|
result.parse(is, length);
|
|
|
return tag;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Reads a size int and a protocol buffer from a DataInput. If the size
|
|
|
+ * is negative, this is interpreted as an indicator that the protocol buffer
|
|
|
+ * is packed with GZIP. In this case, -size bytes are read, and the data is
|
|
|
+ * unpacked with GZIP before constructing the protocol buffer.
|
|
|
+ *
|
|
|
+ * @param protoBufType the protocol buffer type to read
|
|
|
+ * @param dataInput the data input to read from
|
|
|
+ * @return a protocol buffer of the given type
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public static ProtoBuf readProtoBufResponse(ProtoBufType protoBufType,
|
|
|
+ DataInput dataInput) throws IOException {
|
|
|
+ ProtoBuf response = new ProtoBuf(protoBufType);
|
|
|
+ InputStream is = getInputStreamForProtoBufResponse(dataInput);
|
|
|
+ response.parse(is);
|
|
|
+ if (is.read() != -1) {
|
|
|
+ throw new IOException();
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* A wrapper for <code> getProtoValueOrNegativeOne </code> that drills into
|
|
|
* a sub message returning the long value if it exists, returning -1 if it
|
|
|
@@ -162,7 +210,7 @@ public final class ProtoBufUtil {
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
return -1;
|
|
|
} catch (ClassCastException e) {
|
|
|
- return -1;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -182,12 +230,12 @@ public final class ProtoBufUtil {
|
|
|
public static int getSubProtoValueOrDefault(ProtoBuf proto, int sub, int tag,
|
|
|
int defaultValue) {
|
|
|
try {
|
|
|
- return getProtoValueOrDefault(getSubProtoOrNull(proto, sub), tag,
|
|
|
+ return getProtoValueOrDefault(getSubProtoOrNull(proto, sub), tag,
|
|
|
defaultValue);
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
return defaultValue;
|
|
|
} catch (ClassCastException e) {
|
|
|
- return defaultValue;
|
|
|
+ return defaultValue;
|
|
|
}
|
|
|
}
|
|
|
|