001 package org.fusesource.hawtbuf.proto;
002
003 import java.io.IOException;
004 import java.io.InputStream;
005 import java.util.Collection;
006
007 import org.fusesource.hawtbuf.Buffer;
008 import org.fusesource.hawtbuf.BufferOutputStream;
009
010
011 final public class MessageBufferSupport {
012
013 public static final String FORZEN_ERROR_MESSAGE = "Modification not allowed after object has been fozen. Try modifying a copy of this object.";
014
015 static public Buffer toUnframedBuffer(MessageBuffer message) {
016 try {
017 int size = message.serializedSizeUnframed();
018 BufferOutputStream baos = new BufferOutputStream(size);
019 CodedOutputStream output = new CodedOutputStream(baos);
020 message.writeUnframed(output);
021 Buffer rc = baos.toBuffer();
022 assert rc.length == size : "Did not write as much data as expected.";
023 return rc;
024 } catch (IOException e) {
025 throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
026 }
027 }
028
029 static public Buffer toFramedBuffer(MessageBuffer message) {
030 try {
031 int size = message.serializedSizeFramed();
032 BufferOutputStream baos = new BufferOutputStream(size);
033 CodedOutputStream output = new CodedOutputStream(baos);
034 message.writeFramed(output);
035 Buffer rc = baos.toBuffer();
036 assert rc.length==size : "Did not write as much data as expected.";
037 return rc;
038 } catch (IOException e) {
039 throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
040 }
041 }
042
043 public static void writeMessage(CodedOutputStream output, int tag, MessageBuffer message) throws IOException {
044 output.writeTag(tag, WireFormat.WIRETYPE_LENGTH_DELIMITED);
045 message.writeFramed(output);
046 }
047
048 public static int computeMessageSize(int tag, MessageBuffer message) {
049 return CodedOutputStream.computeTagSize(tag) + message.serializedSizeFramed();
050 }
051
052 public static Buffer readFrame(java.io.InputStream input) throws IOException {
053 int length = readRawVarint32(input);
054 byte[] data = new byte[length];
055 int pos = 0;
056 while (pos < length) {
057 int r = input.read(data, pos, length - pos);
058 if (r < 0) {
059 throw new InvalidProtocolBufferException("Input stream ended before a full message frame could be read.");
060 }
061 pos += r;
062 }
063 return new Buffer(data);
064 }
065
066 /**
067 * Read a raw Varint from the stream. If larger than 32 bits, discard the
068 * upper bits.
069 */
070 static public int readRawVarint32(InputStream is) throws IOException {
071 byte tmp = readRawByte(is);
072 if (tmp >= 0) {
073 return tmp;
074 }
075 int result = tmp & 0x7f;
076 if ((tmp = readRawByte(is)) >= 0) {
077 result |= tmp << 7;
078 } else {
079 result |= (tmp & 0x7f) << 7;
080 if ((tmp = readRawByte(is)) >= 0) {
081 result |= tmp << 14;
082 } else {
083 result |= (tmp & 0x7f) << 14;
084 if ((tmp = readRawByte(is)) >= 0) {
085 result |= tmp << 21;
086 } else {
087 result |= (tmp & 0x7f) << 21;
088 result |= (tmp = readRawByte(is)) << 28;
089 if (tmp < 0) {
090 // Discard upper 32 bits.
091 for (int i = 0; i < 5; i++) {
092 if (readRawByte(is) >= 0)
093 return result;
094 }
095 throw new InvalidProtocolBufferException("CodedInputStream encountered a malformed varint.");
096 }
097 }
098 }
099 }
100 return result;
101 }
102
103 static public byte readRawByte(InputStream is) throws IOException {
104 int rc = is.read();
105 if (rc == -1) {
106 throw new InvalidProtocolBufferException("While parsing a protocol message, the input ended unexpectedly " + "in the middle of a field. This could mean either than the " + "input has been truncated or that an embedded message "
107 + "misreported its own length.");
108 }
109 return (byte) rc;
110 }
111
112 static public <T> void addAll(Iterable<T> values, Collection<? super T> list) {
113 if (values instanceof Collection) {
114 @SuppressWarnings("unsafe")
115 Collection<T> collection = (Collection<T>) values;
116 list.addAll(collection);
117 } else {
118 for (T value : values) {
119 list.add(value);
120 }
121 }
122 }
123
124
125 }