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 }