Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.mojo.bindings;
6
7 import org.chromium.mojo.bindings.Interface.Proxy;
8 import org.chromium.mojo.system.DataPipe;
9 import org.chromium.mojo.system.Handle;
10 import org.chromium.mojo.system.InvalidHandle;
11 import org.chromium.mojo.system.MessagePipeHandle;
12 import org.chromium.mojo.system.SharedBufferHandle;
13 import org.chromium.mojo.system.UntypedHandle;
14
15 import java.nio.ByteOrder;
16 import java.nio.charset.Charset;
17
18 /**
19 * A Decoder is a helper class for deserializing a mojo struct. It enables deser ialization of basic
20 * types from a {@link Message} object at a given offset into it's byte buffer.
21 */
22 public class Decoder {
23
24 /**
25 * Helper class to validate the decoded message.
26 */
27 static final class Validator {
28
29 /**
30 * Minimal value for the next handle to deserialize.
31 */
32 private int mMinNextClaimedHandle = 0;
33 /**
34 * Minimal value of the start of the next memory to claim.
35 */
36 private long mMinNextMemory = 0;
37
38 /**
39 * The maximal memory accessible.
40 */
41 private final long mMaxMemory;
42
43 /**
44 * The number of handles in the message.
45 */
46 private final long mNumberOfHandles;
47
48 /**
49 * Constructor.
50 */
51 Validator(long maxMemory, int numberOfHandles) {
52 mMaxMemory = maxMemory;
53 mNumberOfHandles = numberOfHandles;
54 }
55
56 public void claimHandle(int handle) {
57 if (handle < mMinNextClaimedHandle) {
58 throw new DeserializationException(
59 "Trying to access handle out of order.");
60 }
61 if (handle >= mNumberOfHandles) {
62 throw new DeserializationException("Trying to access non present handle.");
63 }
64 mMinNextClaimedHandle = handle + 1;
65 }
66
67 public void claimMemory(long start, long end) {
68 if (start % BindingsHelper.ALIGNMENT != 0) {
69 throw new DeserializationException("Incorrect starting alignment : " + start + ".");
70 }
71 if (start < mMinNextMemory) {
72 throw new DeserializationException("Trying to access memory out of order.");
73 }
74 if (end < start) {
75 throw new DeserializationException("Incorrect memory range.");
76 }
77 if (end > mMaxMemory) {
78 throw new DeserializationException("Trying to access out of rang e memory.");
79 }
80 mMinNextMemory = BindingsHelper.align(end);
81 }
82 }
83
84 /**
85 * The message to deserialize from.
86 */
87 private final Message mMessage;
88
89 /**
90 * The base offset in the byte buffer.
91 */
92 private final int mBaseOffset;
93
94 /**
95 * Validator for the decoded message.
96 */
97 private final Validator mValidator;
98
99 /**
100 * Constructor.
101 *
102 * @param message The message to decode.
103 */
104 public Decoder(Message message) {
105 this(message, new Validator(message.getData().limit(), message.getHandle s().size()), 0);
106 }
107
108 private Decoder(Message message, Validator validator, int baseOffset) {
109 mMessage = message;
110 mMessage.getData().order(ByteOrder.LITTLE_ENDIAN);
111 mBaseOffset = baseOffset;
112 mValidator = validator;
113 }
114
115 /**
116 * Deserializes a {@link DataHeader} at the current position.
117 */
118 public DataHeader readDataHeader() {
119 // Claim the memory for the header.
120 mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE );
121 DataHeader result = readDataHeaderAtOffset(0, false);
122 // Claim the rest of the memory.
123 mValidator.claimMemory(mBaseOffset + DataHeader.HEADER_SIZE, mBaseOffset + result.size);
124 return result;
125 }
126
127 /**
128 * Deserializes a {@link DataHeader} for an union at the given offset.
129 */
130 public DataHeader readDataHeaderForUnion(int offset) {
131 DataHeader result = readDataHeaderAtOffset(offset, true);
132 if (result.size == 0) {
133 if (result.elementsOrVersion != 0) {
134 throw new DeserializationException(
135 "Unexpected version tag for a null union. Expecting 0, f ound: "
136 + result.elementsOrVersion);
137 }
138 } else if (result.size != BindingsHelper.UNION_SIZE) {
139 throw new DeserializationException(
140 "Unexpected size of an union. The size must be 0 for a null union, or 16 for "
141 + "a non-null union.");
142 }
143 return result;
144 }
145
146 /**
147 * @returns a decoder suitable to decode an union defined as the root object of a message.
148 */
149 public Decoder decoderForSerializedUnion() {
150 mValidator.claimMemory(0, BindingsHelper.UNION_SIZE);
151 return this;
152 }
153
154 /**
155 * Deserializes a {@link DataHeader} at the given offset.
156 */
157 private DataHeader readDataHeaderAtOffset(int offset, boolean isUnion) {
158 int size = readInt(offset + DataHeader.SIZE_OFFSET);
159 int elementsOrVersion = readInt(offset + DataHeader.ELEMENTS_OR_VERSION_ OFFSET);
160 if (size < 0) {
161 throw new DeserializationException(
162 "Negative size. Unsigned integers are not valid for java.");
163 }
164 if (elementsOrVersion < 0 && (!isUnion || elementsOrVersion != -1)) {
165 throw new DeserializationException(
166 "Negative elements or version. Unsigned integers are not val id for java.");
167 }
168
169 return new DataHeader(size, elementsOrVersion);
170 }
171
172 public DataHeader readAndValidateDataHeader(DataHeader[] versionArray) {
173 DataHeader header = readDataHeader();
174 int maxVersionIndex = versionArray.length - 1;
175 if (header.elementsOrVersion <= versionArray[maxVersionIndex].elementsOr Version) {
176 DataHeader referenceHeader = null;
177 for (int index = maxVersionIndex; index >= 0; index--) {
178 DataHeader dataHeader = versionArray[index];
179 if (header.elementsOrVersion >= dataHeader.elementsOrVersion) {
180 referenceHeader = dataHeader;
181 break;
182 }
183 }
184 if (referenceHeader == null || referenceHeader.size != header.size) {
185 throw new DeserializationException(
186 "Header doesn't correspond to any known version.");
187 }
188 } else {
189 if (header.size < versionArray[maxVersionIndex].size) {
190 throw new DeserializationException("Message newer than the last known version"
191 + " cannot be shorter than required by the last known ve rsion.");
192 }
193 }
194 return header;
195 }
196
197 /**
198 * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
199 * array where elements are pointers.
200 */
201 public DataHeader readDataHeaderForPointerArray(int expectedLength) {
202 return readDataHeaderForArray(BindingsHelper.POINTER_SIZE, expectedLengt h);
203 }
204
205 /**
206 * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
207 * array where elements are unions.
208 */
209 public DataHeader readDataHeaderForUnionArray(int expectedLength) {
210 return readDataHeaderForArray(BindingsHelper.UNION_SIZE, expectedLength) ;
211 }
212
213 /**
214 * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for a map.
215 */
216 public void readDataHeaderForMap() {
217 DataHeader si = readDataHeader();
218 if (si.size != BindingsHelper.MAP_STRUCT_HEADER.size) {
219 throw new DeserializationException(
220 "Incorrect header for map. The size is incorrect.");
221 }
222 if (si.elementsOrVersion != BindingsHelper.MAP_STRUCT_HEADER.elementsOrV ersion) {
223 throw new DeserializationException(
224 "Incorrect header for map. The version is incorrect.");
225 }
226 }
227
228 /**
229 * Deserializes a byte at the given offset.
230 */
231 public byte readByte(int offset) {
232 validateBufferSize(offset, 1);
233 return mMessage.getData().get(mBaseOffset + offset);
234 }
235
236 /**
237 * Deserializes a boolean at the given offset, re-using any partially read b yte.
238 */
239 public boolean readBoolean(int offset, int bit) {
240 validateBufferSize(offset, 1);
241 return (readByte(offset) & (1 << bit)) != 0;
242 }
243
244 /**
245 * Deserializes a short at the given offset.
246 */
247 public short readShort(int offset) {
248 validateBufferSize(offset, 2);
249 return mMessage.getData().getShort(mBaseOffset + offset);
250 }
251
252 /**
253 * Deserializes an int at the given offset.
254 */
255 public int readInt(int offset) {
256 validateBufferSize(offset, 4);
257 return mMessage.getData().getInt(mBaseOffset + offset);
258 }
259
260 /**
261 * Deserializes a float at the given offset.
262 */
263 public float readFloat(int offset) {
264 validateBufferSize(offset, 4);
265 return mMessage.getData().getFloat(mBaseOffset + offset);
266 }
267
268 /**
269 * Deserializes a long at the given offset.
270 */
271 public long readLong(int offset) {
272 validateBufferSize(offset, 8);
273 return mMessage.getData().getLong(mBaseOffset + offset);
274 }
275
276 /**
277 * Deserializes a double at the given offset.
278 */
279 public double readDouble(int offset) {
280 validateBufferSize(offset, 8);
281 return mMessage.getData().getDouble(mBaseOffset + offset);
282 }
283
284 /**
285 * Deserializes a pointer at the given offset. Returns a Decoder suitable to decode the content
286 * of the pointer.
287 */
288 public Decoder readPointer(int offset, boolean nullable) {
289 int basePosition = mBaseOffset + offset;
290 long pointerOffset = readLong(offset);
291 if (pointerOffset == 0) {
292 if (!nullable) {
293 throw new DeserializationException(
294 "Trying to decode null pointer for a non-nullable type." );
295 }
296 return null;
297 }
298 int newPosition = (int) (basePosition + pointerOffset);
299 // The method |getDecoderAtPosition| will validate that the pointer addr ess is valid.
300 return getDecoderAtPosition(newPosition);
301
302 }
303
304 /**
305 * Deserializes an array of boolean at the given offset.
306 */
307 public boolean[] readBooleans(int offset, int arrayNullability, int expected Length) {
308 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
309 if (d == null) {
310 return null;
311 }
312 DataHeader si = d.readDataHeaderForBooleanArray(expectedLength);
313 byte[] bytes = new byte[(si.elementsOrVersion + 7) / BindingsHelper.ALIG NMENT];
314 d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
315 d.mMessage.getData().get(bytes);
316 boolean[] result = new boolean[si.elementsOrVersion];
317 for (int i = 0; i < bytes.length; ++i) {
318 for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) {
319 int booleanIndex = i * BindingsHelper.ALIGNMENT + j;
320 if (booleanIndex < result.length) {
321 result[booleanIndex] = (bytes[i] & (1 << j)) != 0;
322 }
323 }
324 }
325 return result;
326 }
327
328 /**
329 * Deserializes an array of bytes at the given offset.
330 */
331 public byte[] readBytes(int offset, int arrayNullability, int expectedLength ) {
332 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
333 if (d == null) {
334 return null;
335 }
336 DataHeader si = d.readDataHeaderForArray(1, expectedLength);
337 byte[] result = new byte[si.elementsOrVersion];
338 d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
339 d.mMessage.getData().get(result);
340 return result;
341 }
342
343 /**
344 * Deserializes an array of shorts at the given offset.
345 */
346 public short[] readShorts(int offset, int arrayNullability, int expectedLeng th) {
347 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
348 if (d == null) {
349 return null;
350 }
351 DataHeader si = d.readDataHeaderForArray(2, expectedLength);
352 short[] result = new short[si.elementsOrVersion];
353 d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
354 d.mMessage.getData().asShortBuffer().get(result);
355 return result;
356 }
357
358 /**
359 * Deserializes an array of ints at the given offset.
360 */
361 public int[] readInts(int offset, int arrayNullability, int expectedLength) {
362 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
363 if (d == null) {
364 return null;
365 }
366 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
367 int[] result = new int[si.elementsOrVersion];
368 d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
369 d.mMessage.getData().asIntBuffer().get(result);
370 return result;
371 }
372
373 /**
374 * Deserializes an array of floats at the given offset.
375 */
376 public float[] readFloats(int offset, int arrayNullability, int expectedLeng th) {
377 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
378 if (d == null) {
379 return null;
380 }
381 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
382 float[] result = new float[si.elementsOrVersion];
383 d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
384 d.mMessage.getData().asFloatBuffer().get(result);
385 return result;
386 }
387
388 /**
389 * Deserializes an array of longs at the given offset.
390 */
391 public long[] readLongs(int offset, int arrayNullability, int expectedLength ) {
392 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
393 if (d == null) {
394 return null;
395 }
396 DataHeader si = d.readDataHeaderForArray(8, expectedLength);
397 long[] result = new long[si.elementsOrVersion];
398 d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
399 d.mMessage.getData().asLongBuffer().get(result);
400 return result;
401 }
402
403 /**
404 * Deserializes an array of doubles at the given offset.
405 */
406 public double[] readDoubles(int offset, int arrayNullability, int expectedLe ngth) {
407 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
408 if (d == null) {
409 return null;
410 }
411 DataHeader si = d.readDataHeaderForArray(8, expectedLength);
412 double[] result = new double[si.elementsOrVersion];
413 d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
414 d.mMessage.getData().asDoubleBuffer().get(result);
415 return result;
416 }
417
418 /**
419 * Deserializes an |Handle| at the given offset.
420 */
421 public Handle readHandle(int offset, boolean nullable) {
422 int index = readInt(offset);
423 if (index == -1) {
424 if (!nullable) {
425 throw new DeserializationException(
426 "Trying to decode an invalid handle for a non-nullable t ype.");
427 }
428 return InvalidHandle.INSTANCE;
429 }
430 mValidator.claimHandle(index);
431 return mMessage.getHandles().get(index);
432 }
433
434 /**
435 * Deserializes an |UntypedHandle| at the given offset.
436 */
437 public UntypedHandle readUntypedHandle(int offset, boolean nullable) {
438 return readHandle(offset, nullable).toUntypedHandle();
439 }
440
441 /**
442 * Deserializes a |ConsumerHandle| at the given offset.
443 */
444 public DataPipe.ConsumerHandle readConsumerHandle(int offset, boolean nullab le) {
445 return readUntypedHandle(offset, nullable).toDataPipeConsumerHandle();
446 }
447
448 /**
449 * Deserializes a |ProducerHandle| at the given offset.
450 */
451 public DataPipe.ProducerHandle readProducerHandle(int offset, boolean nullab le) {
452 return readUntypedHandle(offset, nullable).toDataPipeProducerHandle();
453 }
454
455 /**
456 * Deserializes a |MessagePipeHandle| at the given offset.
457 */
458 public MessagePipeHandle readMessagePipeHandle(int offset, boolean nullable) {
459 return readUntypedHandle(offset, nullable).toMessagePipeHandle();
460 }
461
462 /**
463 * Deserializes a |SharedBufferHandle| at the given offset.
464 */
465 public SharedBufferHandle readSharedBufferHandle(int offset, boolean nullabl e) {
466 return readUntypedHandle(offset, nullable).toSharedBufferHandle();
467 }
468
469 /**
470 * Deserializes an interface at the given offset.
471 *
472 * @return a proxy to the service.
473 */
474 public <P extends Proxy> P readServiceInterface(int offset, boolean nullable ,
475 Interface.Manager<?, P> manager) {
476 MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
477 if (!handle.isValid()) {
478 return null;
479 }
480 int version = readInt(offset + BindingsHelper.SERIALIZED_HANDLE_SIZE);
481 return manager.attachProxy(handle, version);
482 }
483
484 /**
485 * Deserializes a |InterfaceRequest| at the given offset.
486 */
487 public <I extends Interface> InterfaceRequest<I> readInterfaceRequest(int of fset,
488 boolean nullable) {
489 MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
490 if (handle == null) {
491 return null;
492 }
493 return new InterfaceRequest<I>(handle);
494 }
495
496 /**
497 * Deserializes a string at the given offset.
498 */
499 public String readString(int offset, boolean nullable) {
500 final int arrayNullability = nullable ? BindingsHelper.ARRAY_NULLABLE : 0;
501 byte[] bytes = readBytes(offset, arrayNullability, BindingsHelper.UNSPEC IFIED_ARRAY_LENGTH);
502 if (bytes == null) {
503 return null;
504 }
505 return new String(bytes, Charset.forName("utf8"));
506 }
507
508 /**
509 * Deserializes an array of |Handle| at the given offset.
510 */
511 public Handle[] readHandles(int offset, int arrayNullability, int expectedLe ngth) {
512 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
513 if (d == null) {
514 return null;
515 }
516 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
517 Handle[] result = new Handle[si.elementsOrVersion];
518 for (int i = 0; i < result.length; ++i) {
519 result[i] = d.readHandle(
520 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SI ZE * i,
521 BindingsHelper.isElementNullable(arrayNullability));
522 }
523 return result;
524 }
525
526 /**
527 * Deserializes an array of |UntypedHandle| at the given offset.
528 */
529 public UntypedHandle[] readUntypedHandles(
530 int offset, int arrayNullability, int expectedLength) {
531 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
532 if (d == null) {
533 return null;
534 }
535 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
536 UntypedHandle[] result = new UntypedHandle[si.elementsOrVersion];
537 for (int i = 0; i < result.length; ++i) {
538 result[i] = d.readUntypedHandle(
539 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SI ZE * i,
540 BindingsHelper.isElementNullable(arrayNullability));
541 }
542 return result;
543 }
544
545 /**
546 * Deserializes an array of |ConsumerHandle| at the given offset.
547 */
548 public DataPipe.ConsumerHandle[] readConsumerHandles(
549 int offset, int arrayNullability, int expectedLength) {
550 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
551 if (d == null) {
552 return null;
553 }
554 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
555 DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.elemen tsOrVersion];
556 for (int i = 0; i < result.length; ++i) {
557 result[i] = d.readConsumerHandle(
558 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SI ZE * i,
559 BindingsHelper.isElementNullable(arrayNullability));
560 }
561 return result;
562 }
563
564 /**
565 * Deserializes an array of |ProducerHandle| at the given offset.
566 */
567 public DataPipe.ProducerHandle[] readProducerHandles(
568 int offset, int arrayNullability, int expectedLength) {
569 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
570 if (d == null) {
571 return null;
572 }
573 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
574 DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.elemen tsOrVersion];
575 for (int i = 0; i < result.length; ++i) {
576 result[i] = d.readProducerHandle(
577 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SI ZE * i,
578 BindingsHelper.isElementNullable(arrayNullability));
579 }
580 return result;
581
582 }
583
584 /**
585 * Deserializes an array of |MessagePipeHandle| at the given offset.
586 */
587 public MessagePipeHandle[] readMessagePipeHandles(
588 int offset, int arrayNullability, int expectedLength) {
589 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
590 if (d == null) {
591 return null;
592 }
593 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
594 MessagePipeHandle[] result = new MessagePipeHandle[si.elementsOrVersion] ;
595 for (int i = 0; i < result.length; ++i) {
596 result[i] = d.readMessagePipeHandle(
597 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SI ZE * i,
598 BindingsHelper.isElementNullable(arrayNullability));
599 }
600 return result;
601
602 }
603
604 /**
605 * Deserializes an array of |SharedBufferHandle| at the given offset.
606 */
607 public SharedBufferHandle[] readSharedBufferHandles(
608 int offset, int arrayNullability, int expectedLength) {
609 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
610 if (d == null) {
611 return null;
612 }
613 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
614 SharedBufferHandle[] result = new SharedBufferHandle[si.elementsOrVersio n];
615 for (int i = 0; i < result.length; ++i) {
616 result[i] = d.readSharedBufferHandle(
617 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SI ZE * i,
618 BindingsHelper.isElementNullable(arrayNullability));
619 }
620 return result;
621
622 }
623
624 /**
625 * Deserializes an array of |ServiceHandle| at the given offset.
626 */
627 public <S extends Interface, P extends Proxy> S[] readServiceInterfaces(
628 int offset, int arrayNullability, int expectedLength, Interface.Mana ger<S, P> manager) {
629 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
630 if (d == null) {
631 return null;
632 }
633 DataHeader si =
634 d.readDataHeaderForArray(BindingsHelper.SERIALIZED_INTERFACE_SIZ E, expectedLength);
635 S[] result = manager.buildArray(si.elementsOrVersion);
636 for (int i = 0; i < result.length; ++i) {
637 // This cast is necessary because java 6 doesn't handle wildcard cor rectly when using
638 // Manager<S, ? extends S>
639 @SuppressWarnings("unchecked")
640 S value = (S) d.readServiceInterface(
641 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_INTERFACE _SIZE * i,
642 BindingsHelper.isElementNullable(arrayNullability), manager) ;
643 result[i] = value;
644 }
645 return result;
646 }
647
648 /**
649 * Deserializes an array of |InterfaceRequest| at the given offset.
650 */
651 public <I extends Interface> InterfaceRequest<I>[] readInterfaceRequests(
652 int offset, int arrayNullability, int expectedLength) {
653 Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNull ability));
654 if (d == null) {
655 return null;
656 }
657 DataHeader si = d.readDataHeaderForArray(4, expectedLength);
658 @SuppressWarnings("unchecked")
659 InterfaceRequest<I>[] result = new InterfaceRequest[si.elementsOrVersion ];
660 for (int i = 0; i < result.length; ++i) {
661 result[i] = d.readInterfaceRequest(
662 DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SI ZE * i,
663 BindingsHelper.isElementNullable(arrayNullability));
664 }
665 return result;
666 }
667
668 /**
669 * Returns a view of this decoder at the offset |offset|.
670 */
671 private Decoder getDecoderAtPosition(int offset) {
672 return new Decoder(mMessage, mValidator, offset);
673 }
674
675 /**
676 * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
677 * array of booleans.
678 */
679 private DataHeader readDataHeaderForBooleanArray(int expectedLength) {
680 DataHeader dataHeader = readDataHeader();
681 if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.elementsOrVer sion + 7) / 8) {
682 throw new DeserializationException("Array header is incorrect.");
683 }
684 if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
685 && dataHeader.elementsOrVersion != expectedLength) {
686 throw new DeserializationException("Incorrect array length. Expected : " + expectedLength
687 + ", but got: " + dataHeader.elementsOrVersion + ".");
688 }
689 return dataHeader;
690 }
691
692 /**
693 * Deserializes a {@link DataHeader} of an array at the given offset.
694 */
695 private DataHeader readDataHeaderForArray(long elementSize, int expectedLeng th) {
696 DataHeader dataHeader = readDataHeader();
697 if (dataHeader.size
698 < (DataHeader.HEADER_SIZE + elementSize * dataHeader.elementsOrV ersion)) {
699 throw new DeserializationException("Array header is incorrect.");
700 }
701 if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
702 && dataHeader.elementsOrVersion != expectedLength) {
703 throw new DeserializationException("Incorrect array length. Expected : " + expectedLength
704 + ", but got: " + dataHeader.elementsOrVersion + ".");
705 }
706 return dataHeader;
707 }
708
709 private void validateBufferSize(int offset, int size) {
710 if (mMessage.getData().limit() < offset + size) {
711 throw new DeserializationException("Buffer is smaller than expected. ");
712 }
713 }
714 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698