1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // http://code.google.com/p/protobuf/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 import java.io.FilterInputStream; 34 import java.io.InputStream; 35 import java.io.IOException; 36 import java.io.OutputStream; 37 import java.util.Collection; 38 39 /** 40 * A partial implementation of the {@link MessageLite} interface which 41 * implements as many methods of that interface as possible in terms of other 42 * methods. 43 * 44 * @author kenton (at) google.com Kenton Varda 45 */ 46 public abstract class AbstractMessageLite implements MessageLite { 47 public ByteString toByteString() { 48 try { 49 final ByteString.CodedBuilder out = 50 ByteString.newCodedBuilder(getSerializedSize()); 51 writeTo(out.getCodedOutput()); 52 return out.build(); 53 } catch (IOException e) { 54 throw new RuntimeException( 55 "Serializing to a ByteString threw an IOException (should " + 56 "never happen).", e); 57 } 58 } 59 60 public byte[] toByteArray() { 61 try { 62 final byte[] result = new byte[getSerializedSize()]; 63 final CodedOutputStream output = CodedOutputStream.newInstance(result); 64 writeTo(output); 65 output.checkNoSpaceLeft(); 66 return result; 67 } catch (IOException e) { 68 throw new RuntimeException( 69 "Serializing to a byte array threw an IOException " + 70 "(should never happen).", e); 71 } 72 } 73 74 public void writeTo(final OutputStream output) throws IOException { 75 final int bufferSize = 76 CodedOutputStream.computePreferredBufferSize(getSerializedSize()); 77 final CodedOutputStream codedOutput = 78 CodedOutputStream.newInstance(output, bufferSize); 79 writeTo(codedOutput); 80 codedOutput.flush(); 81 } 82 83 public void writeDelimitedTo(final OutputStream output) throws IOException { 84 final int serialized = getSerializedSize(); 85 final int bufferSize = CodedOutputStream.computePreferredBufferSize( 86 CodedOutputStream.computeRawVarint32Size(serialized) + serialized); 87 final CodedOutputStream codedOutput = 88 CodedOutputStream.newInstance(output, bufferSize); 89 codedOutput.writeRawVarint32(serialized); 90 writeTo(codedOutput); 91 codedOutput.flush(); 92 } 93 94 /** 95 * A partial implementation of the {@link Message.Builder} interface which 96 * implements as many methods of that interface as possible in terms of 97 * other methods. 98 */ 99 @SuppressWarnings("unchecked") 100 public static abstract class Builder<BuilderType extends Builder> 101 implements MessageLite.Builder { 102 // The compiler produces an error if this is not declared explicitly. 103 @Override 104 public abstract BuilderType clone(); 105 106 public BuilderType mergeFrom(final CodedInputStream input) 107 throws IOException { 108 return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry()); 109 } 110 111 // Re-defined here for return type covariance. 112 public abstract BuilderType mergeFrom( 113 final CodedInputStream input, 114 final ExtensionRegistryLite extensionRegistry) 115 throws IOException; 116 117 public BuilderType mergeFrom(final ByteString data) 118 throws InvalidProtocolBufferException { 119 try { 120 final CodedInputStream input = data.newCodedInput(); 121 mergeFrom(input); 122 input.checkLastTagWas(0); 123 return (BuilderType) this; 124 } catch (InvalidProtocolBufferException e) { 125 throw e; 126 } catch (IOException e) { 127 throw new RuntimeException( 128 "Reading from a ByteString threw an IOException (should " + 129 "never happen).", e); 130 } 131 } 132 133 public BuilderType mergeFrom( 134 final ByteString data, 135 final ExtensionRegistryLite extensionRegistry) 136 throws InvalidProtocolBufferException { 137 try { 138 final CodedInputStream input = data.newCodedInput(); 139 mergeFrom(input, extensionRegistry); 140 input.checkLastTagWas(0); 141 return (BuilderType) this; 142 } catch (InvalidProtocolBufferException e) { 143 throw e; 144 } catch (IOException e) { 145 throw new RuntimeException( 146 "Reading from a ByteString threw an IOException (should " + 147 "never happen).", e); 148 } 149 } 150 151 public BuilderType mergeFrom(final byte[] data) 152 throws InvalidProtocolBufferException { 153 return mergeFrom(data, 0, data.length); 154 } 155 156 public BuilderType mergeFrom(final byte[] data, final int off, 157 final int len) 158 throws InvalidProtocolBufferException { 159 try { 160 final CodedInputStream input = 161 CodedInputStream.newInstance(data, off, len); 162 mergeFrom(input); 163 input.checkLastTagWas(0); 164 return (BuilderType) this; 165 } catch (InvalidProtocolBufferException e) { 166 throw e; 167 } catch (IOException e) { 168 throw new RuntimeException( 169 "Reading from a byte array threw an IOException (should " + 170 "never happen).", e); 171 } 172 } 173 174 public BuilderType mergeFrom( 175 final byte[] data, 176 final ExtensionRegistryLite extensionRegistry) 177 throws InvalidProtocolBufferException { 178 return mergeFrom(data, 0, data.length, extensionRegistry); 179 } 180 181 public BuilderType mergeFrom( 182 final byte[] data, final int off, final int len, 183 final ExtensionRegistryLite extensionRegistry) 184 throws InvalidProtocolBufferException { 185 try { 186 final CodedInputStream input = 187 CodedInputStream.newInstance(data, off, len); 188 mergeFrom(input, extensionRegistry); 189 input.checkLastTagWas(0); 190 return (BuilderType) this; 191 } catch (InvalidProtocolBufferException e) { 192 throw e; 193 } catch (IOException e) { 194 throw new RuntimeException( 195 "Reading from a byte array threw an IOException (should " + 196 "never happen).", e); 197 } 198 } 199 200 public BuilderType mergeFrom(final InputStream input) throws IOException { 201 final CodedInputStream codedInput = CodedInputStream.newInstance(input); 202 mergeFrom(codedInput); 203 codedInput.checkLastTagWas(0); 204 return (BuilderType) this; 205 } 206 207 public BuilderType mergeFrom( 208 final InputStream input, 209 final ExtensionRegistryLite extensionRegistry) 210 throws IOException { 211 final CodedInputStream codedInput = CodedInputStream.newInstance(input); 212 mergeFrom(codedInput, extensionRegistry); 213 codedInput.checkLastTagWas(0); 214 return (BuilderType) this; 215 } 216 217 /** 218 * An InputStream implementations which reads from some other InputStream 219 * but is limited to a particular number of bytes. Used by 220 * mergeDelimitedFrom(). This is intentionally package-private so that 221 * UnknownFieldSet can share it. 222 */ 223 static final class LimitedInputStream extends FilterInputStream { 224 private int limit; 225 226 LimitedInputStream(InputStream in, int limit) { 227 super(in); 228 this.limit = limit; 229 } 230 231 @Override 232 public int available() throws IOException { 233 return Math.min(super.available(), limit); 234 } 235 236 @Override 237 public int read() throws IOException { 238 if (limit <= 0) { 239 return -1; 240 } 241 final int result = super.read(); 242 if (result >= 0) { 243 --limit; 244 } 245 return result; 246 } 247 248 @Override 249 public int read(final byte[] b, final int off, int len) 250 throws IOException { 251 if (limit <= 0) { 252 return -1; 253 } 254 len = Math.min(len, limit); 255 final int result = super.read(b, off, len); 256 if (result >= 0) { 257 limit -= result; 258 } 259 return result; 260 } 261 262 @Override 263 public long skip(final long n) throws IOException { 264 final long result = super.skip(Math.min(n, limit)); 265 if (result >= 0) { 266 limit -= result; 267 } 268 return result; 269 } 270 } 271 272 public boolean mergeDelimitedFrom( 273 final InputStream input, 274 final ExtensionRegistryLite extensionRegistry) 275 throws IOException { 276 final int firstByte = input.read(); 277 if (firstByte == -1) { 278 return false; 279 } 280 final int size = CodedInputStream.readRawVarint32(firstByte, input); 281 final InputStream limitedInput = new LimitedInputStream(input, size); 282 mergeFrom(limitedInput, extensionRegistry); 283 return true; 284 } 285 286 public boolean mergeDelimitedFrom(final InputStream input) 287 throws IOException { 288 return mergeDelimitedFrom(input, 289 ExtensionRegistryLite.getEmptyRegistry()); 290 } 291 292 /** 293 * Construct an UninitializedMessageException reporting missing fields in 294 * the given message. 295 */ 296 protected static UninitializedMessageException 297 newUninitializedMessageException(MessageLite message) { 298 return new UninitializedMessageException(message); 299 } 300 301 /** 302 * Adds the {@code values} to the {@code list}. This is a helper method 303 * used by generated code. Users should ignore it. 304 * 305 * @throws NullPointerException if any of the elements of {@code values} is 306 * null. 307 */ 308 protected static <T> void addAll(final Iterable<T> values, 309 final Collection<? super T> list) { 310 for (final T value : values) { 311 if (value == null) { 312 throw new NullPointerException(); 313 } 314 } 315 if (values instanceof Collection) { 316 @SuppressWarnings("unsafe") final 317 Collection<T> collection = (Collection<T>) values; 318 list.addAll(collection); 319 } else { 320 for (final T value : values) { 321 list.add(value); 322 } 323 } 324 } 325 } 326 } 327