• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.flatbuffers.grpc;
17 
18 import com.google.flatbuffers.Table;
19 import io.grpc.Drainable;
20 import io.grpc.KnownLength;
21 import io.grpc.MethodDescriptor;
22 
23 import javax.annotation.Nullable;
24 import java.io.ByteArrayInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.nio.ByteBuffer;
29 
30 public class FlatbuffersUtils {
31     abstract public static class FBExtactor  <T extends Table> {
extract(InputStream stream)32         T extract (InputStream stream) throws IOException {
33             if (stream instanceof KnownLength) {
34                 int size = stream.available();
35                 ByteBuffer buffer = ByteBuffer.allocate(size);
36                 stream.read(buffer.array());
37                 return extract(buffer);
38             } else
39                 throw new RuntimeException("The class " + stream.getClass().getCanonicalName() + " does not extend from KnownLength ");
40         }
41 
extract(ByteBuffer buffer)42         public abstract T extract(ByteBuffer buffer);
43 
44     }
45 
46     static class FBInputStream extends InputStream implements Drainable, KnownLength {
47         private final ByteBuffer buffer;
48         private final int size;
49         @Nullable private ByteArrayInputStream inputStream;
50 
FBInputStream(ByteBuffer buffer)51         FBInputStream(ByteBuffer buffer) {
52             this.buffer = buffer;
53             this.size = buffer.remaining();
54         }
55 
makeStreamIfNotAlready()56         private void makeStreamIfNotAlready() {
57             if (inputStream == null)
58                 inputStream = new ByteArrayInputStream(buffer.array(), buffer.position(), size);
59         }
60 
61         @Override
drainTo(OutputStream target)62         public int drainTo(OutputStream target) throws IOException {
63             target.write(buffer.array(), buffer.position(), size);
64             return size;
65         }
66 
67         @Override
read()68         public int read() throws IOException {
69             makeStreamIfNotAlready();
70             return inputStream.read();
71         }
72 
73         @Override
read(byte[] b, int off, int len)74         public int read(byte[] b, int off, int len) throws IOException {
75             makeStreamIfNotAlready();
76             if (inputStream == null) {
77                 if (len >= size) {
78                     System.arraycopy(buffer.array(), buffer.position(), b, off, size);
79                     return size;
80                 } else {
81                     makeStreamIfNotAlready();
82                     return inputStream.read(b, off, len);
83                 }
84             } else
85                 return inputStream.read(b, off, len);
86         }
87 
88         @Override
available()89         public int available() throws IOException {
90             return inputStream == null ? size : inputStream.available();
91         }
92 
93     }
94 
marshaller(final Class<T> clazz, final FBExtactor<T> extractor)95     public static <T extends Table> MethodDescriptor.Marshaller<T> marshaller(final Class<T> clazz, final FBExtactor<T> extractor) {
96         return new MethodDescriptor.ReflectableMarshaller<T>() {
97             @Override
98             public Class<T> getMessageClass() {
99                 return clazz;
100             }
101 
102             @Override
103             public InputStream stream(T value) {
104                 return new FBInputStream (value.getByteBuffer());
105             }
106 
107             @Override
108             public T parse(InputStream stream) {
109                 try {
110                     return extractor.extract(stream);
111                 } catch (IOException e) {
112                     throw new RuntimeException(e);
113                 }
114             }
115         };
116     }
117 }
118