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    }