1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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.IOException;
34 import java.nio.ByteBuffer;
35 import java.util.Queue;
36 
37 /** Utilities for serialization. */
38 public class ExperimentalSerializationUtil {
39 
40   /**
41    * Serializes the given message to a byte array using {@link com.google.protobuf.BinaryWriter}.
42    */
toByteArray(T msg)43   public static <T> byte[] toByteArray(T msg) throws IOException {
44     return toByteArray(msg, Protobuf.getInstance().schemaFor(msg));
45   }
46 
47   /**
48    * Serializes the given message to a byte array using {@link com.google.protobuf.BinaryWriter}
49    * with a customized Schema.
50    */
toByteArray(T msg, Schema<T> schema)51   public static <T> byte[] toByteArray(T msg, Schema<T> schema) throws IOException {
52     BinaryWriter writer = BinaryWriter.newHeapInstance(BufferAllocator.unpooled());
53     schema.writeTo(msg, writer);
54 
55     byte[] out = new byte[writer.getTotalBytesWritten()];
56     int outPos = 0;
57     Queue<AllocatedBuffer> buffers = writer.complete();
58     while (true) {
59       AllocatedBuffer buffer = buffers.poll();
60       if (buffer == null) {
61         break;
62       }
63       int length = buffer.limit() - buffer.position();
64       System.arraycopy(
65           buffer.array(), buffer.arrayOffset() + buffer.position(), out, outPos, length);
66       outPos += length;
67     }
68     if (out.length != outPos) {
69       throw new IllegalArgumentException("Failed to serialize test message");
70     }
71     return out;
72   }
73 
74   /** Deserializes a message from the given byte array. */
fromByteArray(byte[] data, Class<T> messageType)75   public static <T> T fromByteArray(byte[] data, Class<T> messageType) {
76     if (Android.isOnAndroidDevice()) {
77       return fromByteArrayFastPath(data, messageType);
78     } else {
79       return fromByteArray(data, messageType, ExtensionRegistryLite.getEmptyRegistry());
80     }
81   }
82 
83   /**
84    * Deserializes a message from the given byte array using {@link com.google.protobuf.BinaryReader}
85    * with an extension registry and a customized Schema.
86    */
fromByteArray( byte[] data, Class<T> messageType, ExtensionRegistryLite extensionRegistry)87   public static <T> T fromByteArray(
88       byte[] data, Class<T> messageType, ExtensionRegistryLite extensionRegistry) {
89     try {
90       Schema<T> schema = Protobuf.getInstance().schemaFor(messageType);
91       T msg = schema.newInstance();
92       schema.mergeFrom(
93           msg, BinaryReader.newInstance(ByteBuffer.wrap(data), true), extensionRegistry);
94       schema.makeImmutable(msg);
95       return msg;
96     } catch (IOException e) {
97       throw new RuntimeException(e);
98     }
99   }
100 
101   /** Deserializes a lite message from the given byte array using fast path. */
fromByteArrayFastPath(byte[] data, Class<T> messageType)102   private static <T> T fromByteArrayFastPath(byte[] data, Class<T> messageType) {
103     try {
104       Schema<T> schema = Protobuf.getInstance().schemaFor(messageType);
105       T msg = schema.newInstance();
106       schema.mergeFrom(msg, data, 0, data.length, new ArrayDecoders.Registers());
107       schema.makeImmutable(msg);
108       return msg;
109     } catch (IOException e) {
110       throw new RuntimeException(e);
111     }
112   }
113 }
114