1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Protocol Buffers - Google's data interchange format 2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Copyright 2008 Google Inc. All rights reserved. 3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/ 4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Redistribution and use in source and binary forms, with or without 6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// modification, are permitted provided that the following conditions are 7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// met: 8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions of source code must retain the above copyright 10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// notice, this list of conditions and the following disclaimer. 11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions in binary form must reproduce the above 12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// copyright notice, this list of conditions and the following disclaimer 13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in the documentation and/or other materials provided with the 14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// distribution. 15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Neither the name of Google Inc. nor the names of its 16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// contributors may be used to endorse or promote products derived from 17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this software without specific prior written permission. 18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpackage com.google.protobuf; 32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport static java.lang.Math.max; 34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport com.google.protobuf.Utf8.UnpairedSurrogateException; 36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.IOException; 38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.OutputStream; 39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.lang.reflect.Field; 40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.nio.BufferOverflowException; 41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.nio.ByteBuffer; 42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.nio.ByteOrder; 43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.security.AccessController; 44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.security.PrivilegedExceptionAction; 45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.logging.Level; 46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.logging.Logger; 47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** 49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Encodes and writes protocol message fields. 50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p>This class contains two kinds of methods: methods that write specific 52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * protocol message constructs and field types (e.g. {@link #writeTag} and 53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@link #writeInt32}) and methods that write low-level values (e.g. 54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are 55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * writing encoded protocol messages, you should use the former methods, but if 56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * you are writing some other format of your own design, use the latter. 57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p>This class is totally unsynchronized. 59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpublic abstract class CodedOutputStream extends ByteOutput { 61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName()); 62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final sun.misc.Unsafe UNSAFE = getUnsafe(); 63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations(); 64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset(); 65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final int FIXED_32_SIZE = 4; 67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final int FIXED_64_SIZE = 8; 68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final int MAX_VARINT_SIZE = 10; 69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. 72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE; 75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * The buffer size used in {@link #newInstance(OutputStream)}. 78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int DEFAULT_BUFFER_SIZE = 4096; 80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns the buffer size to efficiently write dataLength bytes to this 83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * CodedOutputStream. Used by AbstractMessageLite. 84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @return the buffer size to efficiently write dataLength bytes to this 86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * CodedOutputStream. 87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer static int computePreferredBufferSize(int dataLength) { 89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (dataLength > DEFAULT_BUFFER_SIZE) { 90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return DEFAULT_BUFFER_SIZE; 91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return dataLength; 93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream}. 97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or 99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * modify the provided byte arrays. Doing so may result in corrupted data, which would be 100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * difficult to debug. 101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static CodedOutputStream newInstance(final OutputStream output) { 103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return newInstance(output, DEFAULT_BUFFER_SIZE); 104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream} with a given 108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * buffer size. 109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or 111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * modify the provided byte arrays. Doing so may result in corrupted data, which would be 112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * difficult to debug. 113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static CodedOutputStream newInstance(final OutputStream output, final int bufferSize) { 115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new OutputStreamEncoder(output, bufferSize); 116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Create a new {@code CodedOutputStream} that writes directly to the given 120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * byte array. If more bytes are written than fit in the array, 121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * array is faster than writing to an {@code OutputStream}. See also 123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@link ByteString#newCodedBuilder}. 124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static CodedOutputStream newInstance(final byte[] flatArray) { 126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return newInstance(flatArray, 0, flatArray.length); 127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Create a new {@code CodedOutputStream} that writes directly to the given 131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * byte array slice. If more bytes are written than fit in the slice, 132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * array is faster than writing to an {@code OutputStream}. See also 134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@link ByteString#newCodedBuilder}. 135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static CodedOutputStream newInstance( 137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final byte[] flatArray, final int offset, final int length) { 138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new ArrayEncoder(flatArray, offset, length); 139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}. 143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static CodedOutputStream newInstance(ByteBuffer byteBuffer) { 145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (byteBuffer.hasArray()) { 146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new NioHeapEncoder(byteBuffer); 147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new NioEncoder(byteBuffer); 149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}. 153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated the size parameter is no longer used since use of an internal buffer is useless 155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstance(ByteBuffer)} 156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * instead. 157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static CodedOutputStream newInstance(ByteBuffer byteBuffer, 160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @SuppressWarnings("unused") int unused) { 161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return newInstance(byteBuffer); 162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Create a new {@code CodedOutputStream} that writes to the provided {@link ByteOutput}. 166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing 168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * so may result in corrupted data, which would be difficult to debug. 169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param byteOutput the output target for encoded bytes. 171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param bufferSize the size of the internal scratch buffer to be used for string encoding. 172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Setting this to {@code 0} will disable buffering, requiring an allocation for each encoded 173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * string. 174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) { 176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (bufferSize < 0) { 177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalArgumentException("bufferSize must be positive"); 178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new ByteOutputEncoder(byteOutput, bufferSize); 181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Disallow construction outside of this class. 184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private CodedOutputStream() { 185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ----------------------------------------------------------------- 188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Encode and write a tag. */ 190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeTag(int fieldNumber, int wireType) throws IOException; 192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an {@code int32} field, including tag, to the stream. */ 194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeInt32(int fieldNumber, int value) throws IOException; 196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code uint32} field, including tag, to the stream. */ 198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeUInt32(int fieldNumber, int value) throws IOException; 200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code sint32} field, including tag, to the stream. */ 202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSInt32(final int fieldNumber, final int value) throws IOException { 203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(fieldNumber, encodeZigZag32(value)); 204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code fixed32} field, including tag, to the stream. */ 207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeFixed32(int fieldNumber, int value) throws IOException; 209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an {@code sfixed32} field, including tag, to the stream. */ 211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSFixed32(final int fieldNumber, final int value) throws IOException { 212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed32(fieldNumber, value); 213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an {@code int64} field, including tag, to the stream. */ 216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeInt64(final int fieldNumber, final long value) throws IOException { 217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64(fieldNumber, value); 218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code uint64} field, including tag, to the stream. */ 221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeUInt64(int fieldNumber, long value) throws IOException; 223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an {@code sint64} field, including tag, to the stream. */ 225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSInt64(final int fieldNumber, final long value) throws IOException { 226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64(fieldNumber, encodeZigZag64(value)); 227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code fixed64} field, including tag, to the stream. */ 230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeFixed64(int fieldNumber, long value) throws IOException; 232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an {@code sfixed64} field, including tag, to the stream. */ 234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSFixed64(final int fieldNumber, final long value) throws IOException { 235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed64(fieldNumber, value); 236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code float} field, including tag, to the stream. */ 239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeFloat(final int fieldNumber, final float value) throws IOException { 240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed32(fieldNumber, Float.floatToRawIntBits(value)); 241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code double} field, including tag, to the stream. */ 244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeDouble(final int fieldNumber, final double value) throws IOException { 245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed64(fieldNumber, Double.doubleToRawLongBits(value)); 246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bool} field, including tag, to the stream. */ 249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeBool(int fieldNumber, boolean value) throws IOException; 251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write an enum field, including tag, to the stream. The provided value is the numeric 254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * value used to represent the enum value on the wire (not the enum ordinal value). 255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeEnum(final int fieldNumber, final int value) throws IOException { 257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeInt32(fieldNumber, value); 258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code string} field, including tag, to the stream. */ 261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeString(int fieldNumber, String value) throws IOException; 263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bytes} field, including tag, to the stream. */ 265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeBytes(int fieldNumber, ByteString value) throws IOException; 267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bytes} field, including tag, to the stream. */ 269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeByteArray(int fieldNumber, byte[] value) throws IOException; 271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bytes} field, including tag, to the stream. */ 273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, int length) 275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException; 276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a {@code bytes} field, including tag, to the stream. 279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method will write all content of the ByteBuffer regardless of the 280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * current position and limit (i.e., the number of bytes to be written is 281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * value.capacity(), not value.remaining()). Furthermore, this method doesn't 282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * alter the state of the passed-in ByteBuffer. Its position, limit, mark, 283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * etc. will remain unchanged. If you only want to write the remaining bytes 284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * of a ByteBuffer, you can call 285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}. 286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException; 289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a single byte. 292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawByte(final byte value) throws IOException { 294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value); 295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a single byte, represented by an integer value. */ 298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawByte(final int value) throws IOException { 299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write((byte) value); 300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an array of bytes. */ 303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawBytes(final byte[] value) throws IOException { 304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, 0, value.length); 305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write part of an array of bytes. 309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException { 311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a byte string. */ 315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawBytes(final ByteString value) throws IOException { 316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a ByteBuffer. This method will write all content of the ByteBuffer 321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * regardless of the current position and limit (i.e., the number of bytes 322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * to be written is value.capacity(), not value.remaining()). Furthermore, 323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * this method doesn't alter the state of the passed-in ByteBuffer. Its 324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * position, limit, mark, etc. will remain unchanged. If you only want to 325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * write the remaining bytes of a ByteBuffer, you can call 326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code writeRawBytes(byteBuffer.slice())}. 327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeRawBytes(final ByteBuffer value) throws IOException; 330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an embedded message field, including tag, to the stream. */ 332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeMessage(final int fieldNumber, final MessageLite value) 334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException; 335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a MessageSet extension field to the stream. For historical reasons, 338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the wire format differs from normal fields. 339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeMessageSetExtension(final int fieldNumber, final MessageLite value) 342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException; 343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write an unparsed MessageSet extension field to the stream. For 346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * historical reasons, the wire format differs from normal fields. 347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) 350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException; 351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ----------------------------------------------------------------- 353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an {@code int32} field to the stream. */ 355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeInt32NoTag(final int value) throws IOException; 357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code uint32} field to the stream. */ 359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeUInt32NoTag(int value) throws IOException; 361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code sint32} field to the stream. */ 363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSInt32NoTag(final int value) throws IOException { 364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(encodeZigZag32(value)); 365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code fixed32} field to the stream. */ 368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeFixed32NoTag(int value) throws IOException; 370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code sfixed32} field to the stream. */ 372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSFixed32NoTag(final int value) throws IOException { 373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed32NoTag(value); 374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an {@code int64} field to the stream. */ 377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeInt64NoTag(final long value) throws IOException { 378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code uint64} field to the stream. */ 382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeUInt64NoTag(long value) throws IOException; 384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code sint64} field to the stream. */ 386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSInt64NoTag(final long value) throws IOException { 387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(encodeZigZag64(value)); 388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code fixed64} field to the stream. */ 391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeFixed64NoTag(long value) throws IOException; 393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code sfixed64} field to the stream. */ 395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeSFixed64NoTag(final long value) throws IOException { 396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed64NoTag(value); 397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code float} field to the stream. */ 400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeFloatNoTag(final float value) throws IOException { 401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed32NoTag(Float.floatToRawIntBits(value)); 402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code double} field to the stream. */ 405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeDoubleNoTag(final double value) throws IOException { 406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed64NoTag(Double.doubleToRawLongBits(value)); 407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bool} field to the stream. */ 410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeBoolNoTag(final boolean value) throws IOException { 411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write((byte) (value ? 1 : 0)); 412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write an enum field to the stream. The provided value is the numeric 416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * value used to represent the enum value on the wire (not the enum ordinal value). 417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeEnumNoTag(final int value) throws IOException { 419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeInt32NoTag(value); 420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code string} field to the stream. */ 423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(dweis): Document behavior on ill-formed UTF-16 input. 424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeStringNoTag(String value) throws IOException; 426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bytes} field to the stream. */ 428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeBytesNoTag(final ByteString value) throws IOException; 430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bytes} field to the stream. */ 432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeByteArrayNoTag(final byte[] value) throws IOException { 433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArrayNoTag(value, 0, value.length); 434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write an embedded message field to the stream. */ 437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Abstract to avoid overhead of additional virtual method calls. 438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeMessageNoTag(final MessageLite value) throws IOException; 439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer //================================================================= 441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @ExperimentalApi 443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void write(byte value) throws IOException; 445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @ExperimentalApi 447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void write(byte[] value, int offset, int length) throws IOException; 449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @ExperimentalApi 451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeLazy(byte[] value, int offset, int length) throws IOException; 453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void write(ByteBuffer value) throws IOException; 456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @ExperimentalApi 458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void writeLazy(ByteBuffer value) throws IOException; 460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ================================================================= 462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ================================================================= 463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code int32} field, including tag. 467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeInt32Size(final int fieldNumber, final int value) { 469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); 470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code uint32} field, including tag. 475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeUInt32Size(final int fieldNumber, final int value) { 477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); 478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sint32} field, including tag. 483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSInt32Size(final int fieldNumber, final int value) { 485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); 486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code fixed32} field, including tag. 491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeFixed32Size(final int fieldNumber, final int value) { 493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); 494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sfixed32} field, including tag. 499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSFixed32Size(final int fieldNumber, final int value) { 501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); 502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code int64} field, including tag. 507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeInt64Size(final int fieldNumber, final long value) { 509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); 510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code uint64} field, including tag. 515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeUInt64Size(final int fieldNumber, final long value) { 517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); 518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sint64} field, including tag. 523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSInt64Size(final int fieldNumber, final long value) { 525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); 526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code fixed64} field, including tag. 531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeFixed64Size(final int fieldNumber, final long value) { 533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); 534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sfixed64} field, including tag. 539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSFixed64Size(final int fieldNumber, final long value) { 541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); 542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code float} field, including tag. 547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeFloatSize(final int fieldNumber, final float value) { 549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); 550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code double} field, including tag. 555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeDoubleSize(final int fieldNumber, final double value) { 557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); 558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bool} field, including tag. 563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeBoolSize(final int fieldNumber, final boolean value) { 565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); 566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * enum field, including tag. The provided value is the numeric 571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * value used to represent the enum value on the wire (not the enum ordinal value). 572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeEnumSize(final int fieldNumber, final int value) { 574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); 575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code string} field, including tag. 580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeStringSize(final int fieldNumber, final String value) { 582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); 583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bytes} field, including tag. 588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeBytesSize(final int fieldNumber, final ByteString value) { 590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); 591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bytes} field, including tag. 596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeByteArraySize(final int fieldNumber, final byte[] value) { 598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value); 599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bytes} field, including tag. 604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeByteBufferSize(final int fieldNumber, final ByteBuffer value) { 606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeByteBufferSizeNoTag(value); 607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * embedded message in lazy field, including tag. 612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeLazyFieldSize(final int fieldNumber, final LazyFieldLite value) { 614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value); 615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * embedded message field, including tag. 620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeMessageSize(final int fieldNumber, final MessageLite value) { 622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); 623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * MessageSet extension to the stream. For historical reasons, 628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the wire format differs from normal fields. 629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeMessageSetExtensionSize(final int fieldNumber, final MessageLite value) { 631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) 633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value); 634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * unparsed MessageSet extension field to the stream. For 639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * historical reasons, the wire format differs from normal fields. 640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeRawMessageSetExtensionSize( 642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int fieldNumber, final ByteString value) { 643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) 645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value); 646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * lazily parsed MessageSet extension field to the stream. For 651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * historical reasons, the wire format differs from normal fields. 652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeLazyFieldMessageSetExtensionSize( 654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int fieldNumber, final LazyFieldLite value) { 655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) 657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value); 658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ----------------------------------------------------------------- 661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Compute the number of bytes that would be needed to encode a tag. */ 663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeTagSize(final int fieldNumber) { 664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt32SizeNoTag(WireFormat.makeTag(fieldNumber, 0)); 665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code int32} field, including tag. 670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeInt32SizeNoTag(final int value) { 672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value >= 0) { 673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt32SizeNoTag(value); 674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Must sign-extend. 676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return MAX_VARINT_SIZE; 677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code uint32} field. 683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeUInt32SizeNoTag(final int value) { 685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0 << 7)) == 0) { 686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 1; 687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0 << 14)) == 0) { 689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 2; 690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0 << 21)) == 0) { 692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 3; 693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0 << 28)) == 0) { 695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 4; 696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 5; 698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sint32} field. 703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSInt32SizeNoTag(final int value) { 705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt32SizeNoTag(encodeZigZag32(value)); 706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code fixed32} field. 711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) { 713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return FIXED_32_SIZE; 714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sfixed32} field. 719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) { 721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return FIXED_32_SIZE; 722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code int64} field, including tag. 727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeInt64SizeNoTag(final long value) { 729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt64SizeNoTag(value); 730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code uint64} field, including tag. 735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeUInt64SizeNoTag(long value) { 737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // handle two popular special cases up front ... 738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0L << 7)) == 0L) { 739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 1; 740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value < 0L) { 742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 10; 743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ... leaving us with 8 remaining, which we can divide and conquer 745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int n = 2; 746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0L << 35)) != 0L) { 747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer n += 4; value >>>= 28; 748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0L << 21)) != 0L) { 750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer n += 2; value >>>= 14; 751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & (~0L << 14)) != 0L) { 753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer n += 1; 754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return n; 756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sint64} field. 761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSInt64SizeNoTag(final long value) { 763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt64SizeNoTag(encodeZigZag64(value)); 764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code fixed64} field. 769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) { 771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return FIXED_64_SIZE; 772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an 776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code sfixed64} field. 777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) { 779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return FIXED_64_SIZE; 780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code float} field, including tag. 785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) { 787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return FIXED_32_SIZE; 788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code double} field, including tag. 793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) { 795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return FIXED_64_SIZE; 796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bool} field. 801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeBoolSizeNoTag(@SuppressWarnings("unused") final boolean unused) { 803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 1; 804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an enum field. 808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * The provided value is the numeric value used to represent the enum value on the wire 809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * (not the enum ordinal value). 810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeEnumSizeNoTag(final int value) { 812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeInt32SizeNoTag(value); 813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code string} field. 818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeStringSizeNoTag(final String value) { 820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length; 821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer length = Utf8.encodedLength(value); 823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (UnpairedSurrogateException e) { 824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(dweis): Consider using nio Charset methods instead. 825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final byte[] bytes = value.getBytes(Internal.UTF_8); 826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer length = bytes.length; 827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeLengthDelimitedFieldSize(length); 830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an embedded 834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * message stored in lazy field. 835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) { 837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeLengthDelimitedFieldSize(value.getSerializedSize()); 838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bytes} field. 843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeBytesSizeNoTag(final ByteString value) { 845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeLengthDelimitedFieldSize(value.size()); 846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bytes} field. 851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeByteArraySizeNoTag(final byte[] value) { 853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeLengthDelimitedFieldSize(value.length); 854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code bytes} field. 859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeByteBufferSizeNoTag(final ByteBuffer value) { 861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeLengthDelimitedFieldSize(value.capacity()); 862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode an embedded 866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * message field. 867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeMessageSizeNoTag(final MessageLite value) { 869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeLengthDelimitedFieldSize(value.getSerializedSize()); 870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static int computeLengthDelimitedFieldSize(int fieldLength) { 873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt32SizeNoTag(fieldLength) + fieldLength; 874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * into values that can be efficiently encoded with varint. (Otherwise, 879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * negative values must be sign-extended to 64 bits to be varint encoded, 880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * thus always taking 10 bytes on the wire.) 881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param n A signed 32-bit integer. 883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @return An unsigned 32-bit integer, stored in a signed int because 884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Java has no explicit unsigned support. 885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int encodeZigZag32(final int n) { 887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Note: the right-shift must be arithmetic 888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return (n << 1) ^ (n >> 31); 889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers 893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * into values that can be efficiently encoded with varint. (Otherwise, 894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * negative values must be sign-extended to 64 bits to be varint encoded, 895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * thus always taking 10 bytes on the wire.) 896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param n A signed 64-bit integer. 898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @return An unsigned 64-bit integer, stored in a signed int because 899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Java has no explicit unsigned support. 900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static long encodeZigZag64(final long n) { 902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Note: the right-shift must be arithmetic 903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return (n << 1) ^ (n >> 63); 904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ================================================================= 907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Flushes the stream and forces any buffered bytes to be written. This 910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * does not flush the underlying OutputStream. 911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract void flush() throws IOException; 913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * If writing to a flat array, return the space left in the array. 916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Otherwise, throws {@code UnsupportedOperationException}. 917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract int spaceLeft(); 919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Verifies that {@link #spaceLeft()} returns zero. It's common to create 922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * a byte array that is exactly big enough to hold a message, then write to 923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} 924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * after writing verifies that the message was actually as big as expected, 925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * which can help catch bugs. 926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void checkNoSpaceLeft() { 928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (spaceLeft() != 0) { 929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalStateException("Did not write as much data as expected."); 930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * If you create a CodedOutputStream around a simple flat array, you must 935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * not attempt to write more bytes than the array has space. Otherwise, 936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * this exception will be thrown. 937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static class OutOfSpaceException extends IOException { 939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final long serialVersionUID = -6947486886997889499L; 940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final String MESSAGE = 942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "CodedOutputStream was writing to a flat byte array and ran out of space."; 943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer OutOfSpaceException() { 945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer super(MESSAGE); 946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer OutOfSpaceException(Throwable cause) { 949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer super(MESSAGE, cause); 950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Get the total number of bytes successfully written to this stream. The 955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * returned value is not guaranteed to be accurate if exceptions have been 956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * found in the middle of writing. 957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public abstract int getTotalBytesWritten(); 959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ================================================================= 961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** Write a {@code bytes} field to the stream. Visible for testing. */ 963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer abstract void writeByteArrayNoTag(final byte[] value, final int offset, final int length) 964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException; 965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void inefficientWriteStringNoTag(String value, UnpairedSurrogateException cause) 967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer logger.log(Level.WARNING, 969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", cause); 970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Unfortunately there does not appear to be any way to tell Java to encode 972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // UTF-8 directly into our buffer, so we have to let it create its own byte 973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // array and then copy. 974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(dweis): Consider using nio Charset methods instead. 975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final byte[] bytes = value.getBytes(Internal.UTF_8); 976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(bytes.length); 978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeLazy(bytes, 0, bytes.length); 979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (OutOfSpaceException e) { 982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw e; 983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ================================================================= 987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a {@code group} field, including tag, to the stream. 990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated groups are deprecated. 992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeGroup(final int fieldNumber, final MessageLite value) throws IOException { 995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); 996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeGroupNoTag(value); 997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); 998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a {@code group} field to the stream. 1002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated groups are deprecated. 1004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeGroupNoTag(final MessageLite value) throws IOException { 1007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 1008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 1012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code group} field, including tag. 1013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated groups are deprecated. 1015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeGroupSize(final int fieldNumber, final MessageLite value) { 1018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); 1019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a 1023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code group} field. 1024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeGroupSizeNoTag(final MessageLite value) { 1027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return value.getSerializedSize(); 1028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Encode and write a varint. {@code value} is treated as 1032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * unsigned, so it won't be sign-extended if negative. 1033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated use {@link #writeUInt32NoTag} instead. 1035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawVarint32(int value) throws IOException { 1038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value); 1039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Encode and write a varint. 1043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated use {@link #writeUInt64NoTag} instead. 1045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawVarint64(long value) throws IOException { 1048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 1049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a varint. 1053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code value} is treated as unsigned, so it won't be sign-extended if 1054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * negative. 1055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated use {@link #computeUInt32SizeNoTag(int)} instead. 1057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeRawVarint32Size(final int value) { 1060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt32SizeNoTag(value); 1061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Compute the number of bytes that would be needed to encode a varint. 1065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated use {@link #computeUInt64SizeNoTag(long)} instead. 1067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int computeRawVarint64Size(long value) { 1070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return computeUInt64SizeNoTag(value); 1071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a little-endian 32-bit integer. 1075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated Use {@link #writeFixed32NoTag} instead. 1077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawLittleEndian32(final int value) throws IOException { 1080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed32NoTag(value); 1081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Write a little-endian 64-bit integer. 1085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 1086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @deprecated Use {@link #writeFixed64NoTag} instead. 1087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Deprecated 1089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawLittleEndian64(final long value) throws IOException { 1090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed64NoTag(value); 1091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ================================================================= 1094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * A {@link CodedOutputStream} that writes directly to a byte array. 1097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static class ArrayEncoder extends CodedOutputStream { 1099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final byte[] buffer; 1100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final int offset; 1101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final int limit; 1102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private int position; 1103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ArrayEncoder(byte[] buffer, int offset, int length) { 1105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (buffer == null) { 1106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new NullPointerException("buffer"); 1107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((offset | length | (buffer.length - (offset + length))) < 0) { 1109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalArgumentException(String.format( 1110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "Array range is invalid. Buffer.length=%d, offset=%d, length=%d", 1111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.length, offset, length)); 1112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.buffer = buffer; 1114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.offset = offset; 1115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = offset; 1116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer limit = offset + length; 1117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeTag(final int fieldNumber, final int wireType) throws IOException { 1121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); 1122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeInt32(final int fieldNumber, final int value) throws IOException { 1126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeInt32NoTag(value); 1128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeUInt32(final int fieldNumber, final int value) throws IOException { 1132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value); 1134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeFixed32(final int fieldNumber, final int value) throws IOException { 1138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); 1139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed32NoTag(value); 1140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeUInt64(final int fieldNumber, final long value) throws IOException { 1144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 1146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeFixed64(final int fieldNumber, final long value) throws IOException { 1150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); 1151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed64NoTag(value); 1152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeBool(final int fieldNumber, final boolean value) throws IOException { 1156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write((byte) (value ? 1 : 0)); 1158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeString(final int fieldNumber, final String value) throws IOException { 1162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeStringNoTag(value); 1164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeBytes(final int fieldNumber, final ByteString value) throws IOException { 1168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytesNoTag(value); 1170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { 1174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArray(fieldNumber, value, 0, value.length); 1175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeByteArray( 1179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int fieldNumber, final byte[] value, final int offset, final int length) 1180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArrayNoTag(value, offset, length); 1183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeByteBuffer(final int fieldNumber, final ByteBuffer value) 1187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.capacity()); 1190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeRawBytes(value); 1191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeBytesNoTag(final ByteString value) throws IOException { 1195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.size()); 1196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 1197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeByteArrayNoTag(final byte[] value, int offset, int length) 1201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(length); 1203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 1204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawBytes(final ByteBuffer value) throws IOException { 1208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value.hasArray()) { 1209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value.array(), value.arrayOffset(), value.capacity()); 1210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ByteBuffer duplicated = value.duplicate(); 1212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer duplicated.clear(); 1213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(duplicated); 1214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeMessage(final int fieldNumber, final MessageLite value) 1219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessageNoTag(value); 1222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value) 1226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 1228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 1229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); 1230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 1231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) 1235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 1237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 1238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); 1239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 1240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeMessageNoTag(final MessageLite value) throws IOException { 1244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.getSerializedSize()); 1245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 1246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void write(byte value) throws IOException { 1250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = value; 1252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(new IndexOutOfBoundsException( 1254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); 1255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeInt32NoTag(int value) throws IOException { 1260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value >= 0) { 1261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value); 1262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Must sign-extend. 1264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 1265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeUInt32NoTag(int value) throws IOException { 1270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { 1271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer long pos = ARRAY_BASE_OFFSET + position; 1272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7F) == 0) { 1274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) value); 1275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position++; 1276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); 1279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position++; 1280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7F) == 0) { 1287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) value; 1288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value & 0x7F) | 0x80); 1291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException( 1296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer new IndexOutOfBoundsException( 1297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); 1298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeFixed32NoTag(int value) throws IOException { 1304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) (value & 0xFF); 1306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 8) & 0xFF); 1307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 16) & 0xFF); 1308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 24) & 0xFF); 1309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException( 1311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer new IndexOutOfBoundsException( 1312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); 1313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeUInt64NoTag(long value) throws IOException { 1318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { 1319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer long pos = ARRAY_BASE_OFFSET + position; 1320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7FL) == 0) { 1322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) value); 1323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position++; 1324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); 1327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position++; 1328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7FL) == 0) { 1335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) value; 1336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) (((int) value & 0x7F) | 0x80); 1339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException( 1344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer new IndexOutOfBoundsException( 1345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); 1346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeFixed64NoTag(long value) throws IOException { 1352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value) & 0xFF); 1354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 8) & 0xFF); 1355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 16) & 0xFF); 1356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 24) & 0xFF); 1357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); 1358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); 1359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); 1360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); 1361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException( 1363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer new IndexOutOfBoundsException( 1364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); 1365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void write(byte[] value, int offset, int length) throws IOException { 1370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer System.arraycopy(value, offset, buffer, position, length); 1372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position += length; 1373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException( 1375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer new IndexOutOfBoundsException( 1376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String.format("Pos: %d, limit: %d, len: %d", position, limit, length))); 1377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeLazy(byte[] value, int offset, int length) throws IOException { 1382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 1383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void write(ByteBuffer value) throws IOException { 1387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int length = value.remaining(); 1388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.get(buffer, position, length); 1390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position += length; 1391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException( 1393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer new IndexOutOfBoundsException( 1394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String.format("Pos: %d, limit: %d, len: %d", position, limit, length))); 1395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeLazy(ByteBuffer value) throws IOException { 1400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value); 1401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final void writeStringNoTag(String value) throws IOException { 1405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int oldPosition = position; 1406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()), 1408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // and at most 3 times of it. We take advantage of this in both branches below. 1409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR; 1410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength); 1411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); 1412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (minLengthVarIntSize == maxLengthVarIntSize) { 1413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition + minLengthVarIntSize; 1414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int newPosition = Utf8.encode(value, buffer, position, spaceLeft()); 1415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Since this class is stateful and tracks the position, we rewind and store the state, 1416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // prepend the length, then reset it back to the end of the string. 1417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition; 1418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = newPosition - oldPosition - minLengthVarIntSize; 1419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(length); 1420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = newPosition; 1421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = Utf8.encodedLength(value); 1423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(length); 1424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = Utf8.encode(value, buffer, position, spaceLeft()); 1425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (UnpairedSurrogateException e) { 1427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Roll back the change - we fall back to inefficient path. 1428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition; 1429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(nathanmittler): We should throw an IOException here instead. 1431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer inefficientWriteStringNoTag(value, e); 1432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void flush() { 1439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Do nothing. 1440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final int spaceLeft() { 1444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return limit - position; 1445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final int getTotalBytesWritten() { 1449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return position - offset; 1450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are 1455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * done directly to the underlying array. The buffer position is only updated after a flush. 1456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final class NioHeapEncoder extends ArrayEncoder { 1458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final ByteBuffer byteBuffer; 1459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private int initialPosition; 1460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer NioHeapEncoder(ByteBuffer byteBuffer) { 1462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), 1463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer byteBuffer.remaining()); 1464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.byteBuffer = byteBuffer; 1465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.initialPosition = byteBuffer.position(); 1466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void flush() { 1470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Update the position on the buffer. 1471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer byteBuffer.position(initialPosition + getTotalBytesWritten()); 1472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}. 1477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final class NioEncoder extends CodedOutputStream { 1479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final ByteBuffer originalBuffer; 1480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final ByteBuffer buffer; 1481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final int initialPosition; 1482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer NioEncoder(ByteBuffer buffer) { 1484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.originalBuffer = buffer; 1485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN); 1486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer initialPosition = buffer.position(); 1487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeTag(final int fieldNumber, final int wireType) throws IOException { 1491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); 1492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeInt32(final int fieldNumber, final int value) throws IOException { 1496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeInt32NoTag(value); 1498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt32(final int fieldNumber, final int value) throws IOException { 1502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value); 1504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed32(final int fieldNumber, final int value) throws IOException { 1508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); 1509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed32NoTag(value); 1510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt64(final int fieldNumber, final long value) throws IOException { 1514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 1516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed64(final int fieldNumber, final long value) throws IOException { 1520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); 1521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeFixed64NoTag(value); 1522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBool(final int fieldNumber, final boolean value) throws IOException { 1526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write((byte) (value ? 1 : 0)); 1528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeString(final int fieldNumber, final String value) throws IOException { 1532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeStringNoTag(value); 1534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { 1538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytesNoTag(value); 1540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { 1544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArray(fieldNumber, value, 0, value.length); 1545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArray( 1549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int fieldNumber, final byte[] value, final int offset, final int length) 1550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArrayNoTag(value, offset, length); 1553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) 1557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.capacity()); 1560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeRawBytes(value); 1561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessage(final int fieldNumber, final MessageLite value) 1565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 1567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessageNoTag(value); 1568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) 1572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 1574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 1575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); 1576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 1577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) 1581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 1582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 1583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 1584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); 1585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 1586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessageNoTag(final MessageLite value) throws IOException { 1590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.getSerializedSize()); 1591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 1592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(byte value) throws IOException { 1596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.put(value); 1598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (BufferOverflowException e) { 1599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBytesNoTag(final ByteString value) throws IOException { 1605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.size()); 1606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 1607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException { 1611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(length); 1612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 1613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeRawBytes(final ByteBuffer value) throws IOException { 1617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value.hasArray()) { 1618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value.array(), value.arrayOffset(), value.capacity()); 1619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ByteBuffer duplicated = value.duplicate(); 1621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer duplicated.clear(); 1622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(duplicated); 1623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeInt32NoTag(int value) throws IOException { 1628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value >= 0) { 1629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value); 1630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Must sign-extend. 1632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 1633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt32NoTag(int value) throws IOException { 1638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7F) == 0) { 1641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.put((byte) value); 1642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.put((byte) ((value & 0x7F) | 0x80)); 1645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (BufferOverflowException e) { 1649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed32NoTag(int value) throws IOException { 1655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.putInt(value); 1657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (BufferOverflowException e) { 1658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt64NoTag(long value) throws IOException { 1664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7FL) == 0) { 1667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.put((byte) value); 1668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.put((byte) (((int) value & 0x7F) | 0x80)); 1671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (BufferOverflowException e) { 1675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed64NoTag(long value) throws IOException { 1681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.putLong(value); 1683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (BufferOverflowException e) { 1684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(byte[] value, int offset, int length) throws IOException { 1690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.put(value, offset, length); 1692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (BufferOverflowException e) { 1695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeLazy(byte[] value, int offset, int length) throws IOException { 1701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 1702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(ByteBuffer value) throws IOException { 1706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.put(value); 1708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (BufferOverflowException e) { 1709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeLazy(ByteBuffer value) throws IOException { 1715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value); 1716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeStringNoTag(String value) throws IOException { 1720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int startPos = buffer.position(); 1721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()), 1723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // and at most 3 times of it. We take advantage of this in both branches below. 1724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR; 1725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize); 1726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); 1727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (minLengthVarIntSize == maxLengthVarIntSize) { 1728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Save the current position and increment past the length field. We'll come back 1729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // and write the length field after the encoding is complete. 1730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int startOfBytes = buffer.position() + minLengthVarIntSize; 1731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.position(startOfBytes); 1732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Encode the string. 1734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer encode(value); 1735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Now go back to the beginning and write the length. 1737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int endOfBytes = buffer.position(); 1738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.position(startPos); 1739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(endOfBytes - startOfBytes); 1740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Reposition the buffer past the written data. 1742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.position(endOfBytes); 1743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int length = Utf8.encodedLength(value); 1745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(length); 1746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer encode(value); 1747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (UnpairedSurrogateException e) { 1749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Roll back the change and convert to an IOException. 1750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer.position(startPos); 1751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(nathanmittler): We should throw an IOException here instead. 1753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer inefficientWriteStringNoTag(value, e); 1754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IllegalArgumentException e) { 1755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Thrown by buffer.position() if out of range. 1756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void flush() { 1762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Update the position of the original buffer. 1763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer originalBuffer.position(buffer.position()); 1764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public int spaceLeft() { 1768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return buffer.remaining(); 1769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public int getTotalBytesWritten() { 1773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return buffer.position() - initialPosition; 1774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private void encode(String value) throws IOException { 1777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 1778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Utf8.encodeUtf8(value, buffer); 1779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 1780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 1781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Abstract base class for buffered encoders. 1787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private abstract static class AbstractBufferedEncoder extends CodedOutputStream { 1789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final byte[] buffer; 1790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int limit; 1791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int position; 1792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int totalBytesWritten; 1793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer AbstractBufferedEncoder(int bufferSize) { 1795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (bufferSize < 0) { 1796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalArgumentException("bufferSize must be >= 0"); 1797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // As an optimization, we require that the buffer be able to store at least 2 1799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // varints so that we can buffer any integer write (tag + value). This reduces the 1800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // number of range checks for a single write to 1 (i.e. if there is not enough space 1801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // to buffer the tag+value, flush and then buffer it). 1802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.buffer = new byte[max(bufferSize, MAX_VARINT_SIZE * 2)]; 1803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.limit = buffer.length; 1804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final int spaceLeft() { 1808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new UnsupportedOperationException( 1809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "spaceLeft() can only be called on CodedOutputStreams that are " 1810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + "writing to a flat array or ByteBuffer."); 1811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public final int getTotalBytesWritten() { 1815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return totalBytesWritten; 1816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method does not perform bounds checking on the array. Checking array bounds is the 1820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * responsibility of the caller. 1821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void buffer(byte value) { 1823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = value; 1824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten++; 1825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method does not perform bounds checking on the array. Checking array bounds is the 1829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * responsibility of the caller. 1830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void bufferTag(final int fieldNumber, final int wireType) { 1832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); 1833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method does not perform bounds checking on the array. Checking array bounds is the 1837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * responsibility of the caller. 1838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void bufferInt32NoTag(final int value) { 1840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value >= 0) { 1841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(value); 1842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Must sign-extend. 1844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt64NoTag(value); 1845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method does not perform bounds checking on the array. Checking array bounds is the 1850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * responsibility of the caller. 1851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void bufferUInt32NoTag(int value) { 1853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HAS_UNSAFE_ARRAY_OPERATIONS) { 1854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final long originalPos = ARRAY_BASE_OFFSET + position; 1855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer long pos = originalPos; 1856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7F) == 0) { 1858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) value); 1859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 1860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); 1862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int delta = (int) (pos - originalPos); 1866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position += delta; 1867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += delta; 1868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7F) == 0) { 1871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) value; 1872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten++; 1873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value & 0x7F) | 0x80); 1876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten++; 1877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method does not perform bounds checking on the array. Checking array bounds is the 1885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * responsibility of the caller. 1886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void bufferUInt64NoTag(long value) { 1888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HAS_UNSAFE_ARRAY_OPERATIONS) { 1889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final long originalPos = ARRAY_BASE_OFFSET + position; 1890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer long pos = originalPos; 1891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7FL) == 0) { 1893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) value); 1894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 1895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); 1897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int delta = (int) (pos - originalPos); 1901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position += delta; 1902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += delta; 1903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 1905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if ((value & ~0x7FL) == 0) { 1906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) value; 1907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten++; 1908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 1909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 1910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) (((int) value & 0x7F) | 0x80); 1911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten++; 1912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value >>>= 7; 1913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method does not perform bounds checking on the array. Checking array bounds is the 1920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * responsibility of the caller. 1921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void bufferFixed32NoTag(int value) { 1923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) (value & 0xFF); 1924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 8) & 0xFF); 1925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 16) & 0xFF); 1926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 24) & 0xFF); 1927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += FIXED_32_SIZE; 1928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This method does not perform bounds checking on the array. Checking array bounds is the 1932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * responsibility of the caller. 1933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final void bufferFixed64NoTag(long value) { 1935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) (value & 0xFF); 1936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 8) & 0xFF); 1937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 16) & 0xFF); 1938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((value >> 24) & 0xFF); 1939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); 1940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); 1941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); 1942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); 1943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += FIXED_64_SIZE; 1944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 1948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * A {@link CodedOutputStream} that decorates a {@link ByteOutput}. It internal buffer only to 1949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * support string encoding operations. All other writes are just passed through to the 1950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@link ByteOutput}. 1951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 1952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final class ByteOutputEncoder extends AbstractBufferedEncoder { 1953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final ByteOutput out; 1954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ByteOutputEncoder(ByteOutput out, int bufferSize) { 1956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer super(bufferSize); 1957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (out == null) { 1958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new NullPointerException("out"); 1959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.out = out; 1961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeTag(final int fieldNumber, final int wireType) throws IOException { 1965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); 1966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeInt32(final int fieldNumber, final int value) throws IOException { 1970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE * 2); 1971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferInt32NoTag(value); 1973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt32(final int fieldNumber, final int value) throws IOException { 1977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE * 2); 1978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(value); 1980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed32(final int fieldNumber, final int value) throws IOException { 1984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE); 1985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); 1986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed32NoTag(value); 1987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt64(final int fieldNumber, final long value) throws IOException { 1991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE * 2); 1992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 1993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt64NoTag(value); 1994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 1995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 1996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 1997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed64(final int fieldNumber, final long value) throws IOException { 1998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE); 1999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); 2000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed64NoTag(value); 2001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBool(final int fieldNumber, final boolean value) throws IOException { 2005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE + 1); 2006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 2007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer((byte) (value ? 1 : 0)); 2008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeString(final int fieldNumber, final String value) throws IOException { 2012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeStringNoTag(value); 2014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { 2018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytesNoTag(value); 2020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { 2024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArray(fieldNumber, value, 0, value.length); 2025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArray( 2029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int fieldNumber, final byte[] value, final int offset, final int length) 2030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArrayNoTag(value, offset, length); 2033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) 2037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.capacity()); 2040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeRawBytes(value); 2041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBytesNoTag(final ByteString value) throws IOException { 2045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.size()); 2046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 2047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException { 2051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(length); 2052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 2053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeRawBytes(final ByteBuffer value) throws IOException { 2057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value.hasArray()) { 2058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value.array(), value.arrayOffset(), value.capacity()); 2059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ByteBuffer duplicated = value.duplicate(); 2061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer duplicated.clear(); 2062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(duplicated); 2063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessage(final int fieldNumber, final MessageLite value) 2068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessageNoTag(value); 2071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) 2075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 2077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 2078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); 2079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 2080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) 2084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 2086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 2087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); 2088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 2089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessageNoTag(final MessageLite value) throws IOException { 2093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.getSerializedSize()); 2094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 2095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(byte value) throws IOException { 2099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (position == limit) { 2100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer(value); 2104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeInt32NoTag(int value) throws IOException { 2108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value >= 0) { 2109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value); 2110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Must sign-extend. 2112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 2113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt32NoTag(int value) throws IOException { 2118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE); 2119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(value); 2120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed32NoTag(final int value) throws IOException { 2124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(FIXED_32_SIZE); 2125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed32NoTag(value); 2126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt64NoTag(long value) throws IOException { 2130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE); 2131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt64NoTag(value); 2132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed64NoTag(final long value) throws IOException { 2136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(FIXED_64_SIZE); 2137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed64NoTag(value); 2138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeStringNoTag(String value) throws IOException { 2142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()), 2143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // and at most 3 times of it. We take advantage of this in both branches below. 2144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR; 2145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength); 2146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // If we are streaming and the potential length is too big to fit in our buffer, we take the 2148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // slower path. 2149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (maxLengthVarIntSize + maxLength > limit) { 2150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes() 2151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // does the same internally and then does *another copy* to return a byte[] of exactly the 2152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // right size. We can skip that copy and just writeRawBytes up to the actualLength of the 2153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // UTF-8 encoded bytes. 2154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final byte[] encodedBytes = new byte[maxLength]; 2155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength); 2156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(actualLength); 2157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeLazy(encodedBytes, 0, actualLength); 2158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 2159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Fast path: we have enough space available in our buffer for the string... 2162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (maxLengthVarIntSize + maxLength > limit - position) { 2163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Flush to free up space. 2164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int oldPosition = position; 2168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 2169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Optimize for the case where we know this length results in a constant varint length as 2170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // this saves a pass for measuring the length of the string. 2171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); 2172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (minLengthVarIntSize == maxLengthVarIntSize) { 2174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition + minLengthVarIntSize; 2175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int newPosition = Utf8.encode(value, buffer, position, limit - position); 2176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Since this class is stateful and tracks the position, we rewind and store the state, 2177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // prepend the length, then reset it back to the end of the string. 2178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition; 2179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = newPosition - oldPosition - minLengthVarIntSize; 2180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(length); 2181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = newPosition; 2182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = Utf8.encodedLength(value); 2185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(length); 2186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = Utf8.encode(value, buffer, position, length); 2187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (UnpairedSurrogateException e) { 2190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Roll back the change and convert to an IOException. 2191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten -= position - oldPosition; 2192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition; 2193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(nathanmittler): We should throw an IOException here instead. 2195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer inefficientWriteStringNoTag(value, e); 2196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (IndexOutOfBoundsException e) { 2197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 2198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void flush() throws IOException { 2203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (position > 0) { 2204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Flush the buffer. 2205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(byte[] value, int offset, int length) throws IOException { 2211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flush(); 2212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.write(value, offset, length); 2213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeLazy(byte[] value, int offset, int length) throws IOException { 2218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flush(); 2219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.writeLazy(value, offset, length); 2220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(ByteBuffer value) throws IOException { 2225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flush(); 2226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = value.remaining(); 2227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.write(value); 2228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeLazy(ByteBuffer value) throws IOException { 2233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flush(); 2234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = value.remaining(); 2235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.writeLazy(value); 2236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private void flushIfNotAvailable(int requiredSize) throws IOException { 2240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (limit - position < requiredSize) { 2241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private void doFlush() throws IOException { 2246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.write(buffer, 0, position); 2247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = 0; 2248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 2252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * An {@link CodedOutputStream} that decorates an {@link OutputStream}. It performs internal 2253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * buffering to optimize writes to the {@link OutputStream}. 2254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 2255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final class OutputStreamEncoder extends AbstractBufferedEncoder { 2256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private final OutputStream out; 2257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer OutputStreamEncoder(OutputStream out, int bufferSize) { 2259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer super(bufferSize); 2260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (out == null) { 2261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new NullPointerException("out"); 2262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.out = out; 2264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeTag(final int fieldNumber, final int wireType) throws IOException { 2268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); 2269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeInt32(final int fieldNumber, final int value) throws IOException { 2273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE * 2); 2274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 2275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferInt32NoTag(value); 2276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt32(final int fieldNumber, final int value) throws IOException { 2280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE * 2); 2281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 2282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(value); 2283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed32(final int fieldNumber, final int value) throws IOException { 2287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE); 2288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); 2289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed32NoTag(value); 2290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt64(final int fieldNumber, final long value) throws IOException { 2294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE * 2); 2295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 2296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt64NoTag(value); 2297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed64(final int fieldNumber, final long value) throws IOException { 2301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE); 2302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); 2303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed64NoTag(value); 2304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBool(final int fieldNumber, final boolean value) throws IOException { 2308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE + 1); 2309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); 2310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer((byte) (value ? 1 : 0)); 2311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeString(final int fieldNumber, final String value) throws IOException { 2315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeStringNoTag(value); 2317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { 2321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytesNoTag(value); 2323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { 2327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArray(fieldNumber, value, 0, value.length); 2328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArray( 2332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int fieldNumber, final byte[] value, final int offset, final int length) 2333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeByteArrayNoTag(value, offset, length); 2336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) 2340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.capacity()); 2343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeRawBytes(value); 2344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeBytesNoTag(final ByteString value) throws IOException { 2348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.size()); 2349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 2350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException { 2354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(length); 2355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 2356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeRawBytes(final ByteBuffer value) throws IOException { 2360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value.hasArray()) { 2361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value.array(), value.arrayOffset(), value.capacity()); 2362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ByteBuffer duplicated = value.duplicate(); 2364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer duplicated.clear(); 2365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(duplicated); 2366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessage(final int fieldNumber, final MessageLite value) 2371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); 2373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessageNoTag(value); 2374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) 2378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 2380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 2381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); 2382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 2383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) 2387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); 2389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); 2390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); 2391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); 2392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeMessageNoTag(final MessageLite value) throws IOException { 2396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value.getSerializedSize()); 2397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.writeTo(this); 2398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(byte value) throws IOException { 2402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (position == limit) { 2403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer buffer(value); 2407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeInt32NoTag(int value) throws IOException { 2411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value >= 0) { 2412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(value); 2413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Must sign-extend. 2415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt64NoTag(value); 2416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt32NoTag(int value) throws IOException { 2421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE); 2422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(value); 2423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed32NoTag(final int value) throws IOException { 2427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(FIXED_32_SIZE); 2428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed32NoTag(value); 2429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeUInt64NoTag(long value) throws IOException { 2433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(MAX_VARINT_SIZE); 2434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt64NoTag(value); 2435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeFixed64NoTag(final long value) throws IOException { 2439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer flushIfNotAvailable(FIXED_64_SIZE); 2440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferFixed64NoTag(value); 2441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeStringNoTag(String value) throws IOException { 2445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 2446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()), 2447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // and at most 3 times of it. We take advantage of this in both branches below. 2448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR; 2449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength); 2450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // If we are streaming and the potential length is too big to fit in our buffer, we take the 2452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // slower path. 2453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (maxLengthVarIntSize + maxLength > limit) { 2454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes() 2455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // does the same internally and then does *another copy* to return a byte[] of exactly the 2456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // right size. We can skip that copy and just writeRawBytes up to the actualLength of the 2457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // UTF-8 encoded bytes. 2458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final byte[] encodedBytes = new byte[maxLength]; 2459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength); 2460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeUInt32NoTag(actualLength); 2461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer writeLazy(encodedBytes, 0, actualLength); 2462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 2463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Fast path: we have enough space available in our buffer for the string... 2466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (maxLengthVarIntSize + maxLength > limit - position) { 2467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Flush to free up space. 2468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Optimize for the case where we know this length results in a constant varint length as 2472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // this saves a pass for measuring the length of the string. 2473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); 2474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int oldPosition = position; 2475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int length; 2476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 2477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (minLengthVarIntSize == maxLengthVarIntSize) { 2478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition + minLengthVarIntSize; 2479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int newPosition = Utf8.encode(value, buffer, position, limit - position); 2480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Since this class is stateful and tracks the position, we rewind and store the 2481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // state, prepend the length, then reset it back to the end of the string. 2482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition; 2483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer length = newPosition - oldPosition - minLengthVarIntSize; 2484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(length); 2485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = newPosition; 2486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer length = Utf8.encodedLength(value); 2488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer bufferUInt32NoTag(length); 2489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = Utf8.encode(value, buffer, position, length); 2490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (UnpairedSurrogateException e) { 2493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Be extra careful and restore the original position for retrying the write with the 2494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // less efficient path. 2495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten -= position - oldPosition; 2496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = oldPosition; 2497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw e; 2498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (ArrayIndexOutOfBoundsException e) { 2499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new OutOfSpaceException(e); 2500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (UnpairedSurrogateException e) { 2502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer inefficientWriteStringNoTag(value, e); 2503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void flush() throws IOException { 2508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (position > 0) { 2509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Flush the buffer. 2510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(byte[] value, int offset, int length) 2516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 2517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (limit - position >= length) { 2518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // We have room in the current buffer. 2519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer System.arraycopy(value, offset, buffer, position, length); 2520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position += length; 2521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Write extends past current buffer. Fill the rest of this buffer and 2524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // flush. 2525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int bytesWritten = limit - position; 2526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer System.arraycopy(value, offset, buffer, position, bytesWritten); 2527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer offset += bytesWritten; 2528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer length -= bytesWritten; 2529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = limit; 2530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += bytesWritten; 2531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Now deal with the rest. 2534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Since we have an output stream, this is our buffer 2535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // and buffer offset == 0 2536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (length <= limit) { 2537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Fits in new buffer. 2538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer System.arraycopy(value, offset, buffer, 0, length); 2539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = length; 2540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Write is very big. Let's do it all at once. 2542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.write(value, offset, length); 2543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeLazy(byte[] value, int offset, int length) throws IOException { 2550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value, offset, length); 2551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void write(ByteBuffer value) throws IOException { 2555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = value.remaining(); 2556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (limit - position >= length) { 2557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // We have room in the current buffer. 2558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.get(buffer, position, length); 2559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position += length; 2560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 2562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Write extends past current buffer. Fill the rest of this buffer and 2563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // flush. 2564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int bytesWritten = limit - position; 2565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.get(buffer, position, bytesWritten); 2566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer length -= bytesWritten; 2567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = limit; 2568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += bytesWritten; 2569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Now deal with the rest. 2572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Since we have an output stream, this is our buffer 2573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // and buffer offset == 0 2574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (length > limit) { 2575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Copy data into the buffer before writing it to OutputStream. 2576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.get(buffer, 0, limit); 2577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.write(buffer, 0, limit); 2578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer length -= limit; 2579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += limit; 2580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value.get(buffer, 0, length); 2582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = length; 2583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer totalBytesWritten += length; 2584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void writeLazy(ByteBuffer value) throws IOException { 2589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer write(value); 2590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private void flushIfNotAvailable(int requiredSize) throws IOException { 2593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (limit - position < requiredSize) { 2594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer doFlush(); 2595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private void doFlush() throws IOException { 2599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer out.write(buffer, 0, position); 2600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer position = 0; 2601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 2605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this 2606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * platform. 2607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 2608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static sun.misc.Unsafe getUnsafe() { 2609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sun.misc.Unsafe unsafe = null; 2610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 2611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.misc.Unsafe>() { 2612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 2613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public sun.misc.Unsafe run() throws Exception { 2614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; 2615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Field f : k.getDeclaredFields()) { 2617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer f.setAccessible(true); 2618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Object x = f.get(null); 2619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (k.isInstance(x)) { 2620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return k.cast(x); 2621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // The sun.misc.Unsafe field does not exist. 2624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return null; 2625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer }); 2627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (Throwable e) { 2628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError 2629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // for Unsafe. 2630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer logger.log(Level.FINEST, "sun.misc.Unsafe: {}", 2633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer unsafe != null ? "available" : "unavailable"); 2634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return unsafe; 2635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 2638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Indicates whether or not unsafe array operations are supported on this platform. 2639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 2640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(nathanmittler): Add support for Android's MemoryBlock. 2641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static boolean supportsUnsafeArrayOperations() { 2642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer boolean supported = false; 2643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (UNSAFE != null) { 2644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 2645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.getClass().getMethod("arrayBaseOffset", Class.class); 2646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UNSAFE.getClass().getMethod("putByte", Object.class, long.class, byte.class); 2647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer supported = true; 2648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (Throwable e) { 2649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Do nothing. 2650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer logger.log(Level.FINEST, "Unsafe array operations: {}", 2653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer supported ? "available" : "unavailable"); 2654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return supported; 2655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 2657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 2658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not 2659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * available. 2660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 2661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static <T> int byteArrayBaseOffset() { 2662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1; 2663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 2664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 2665