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

Side by Side Diff: mojo/public/dart/src/codec.dart

Issue 1132063007: Rationalize Dart mojo and sky package structure (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « mojo/public/dart/src/buffer.dart ('k') | mojo/public/dart/src/control_message.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 part of bindings;
6
7 int align(int size) => size + (kAlignment - (size % kAlignment)) % kAlignment;
8
9 const int kAlignment = 8;
10 const int kSerializedHandleSize = 4;
11 const int kSerializedInterfaceSize = 8; // 4-byte handle + 4-byte version
12 const int kPointerSize = 8;
13 const StructDataHeader kMapStructHeader = const StructDataHeader(24, 0);
14 const int kUnspecifiedArrayLength = -1;
15 const int kNothingNullable = 0;
16 const int kArrayNullable = (1 << 0);
17 const int kElementNullable = (1 << 1);
18
19 bool isArrayNullable(int nullability) => (nullability & kArrayNullable) > 0;
20 bool isElementNullable(int nullability) => (nullability & kElementNullable) > 0;
21
22 class StructDataHeader {
23 static const int kHeaderSize = 8;
24 static const int kSizeOffset = 0;
25 static const int kVersionOffset = 4;
26 final int size;
27 final int version;
28
29 const StructDataHeader(this.size, this.version);
30
31 String toString() => "StructDataHeader($size, $version)";
32 }
33
34 class ArrayDataHeader {
35 static const int kHeaderSize = 8;
36 static const int kSizeOffset = 0;
37 static const int kNumElementsOffset = 4;
38 final int size;
39 final int numElements;
40
41 const ArrayDataHeader(this.size, this.numElements);
42
43 String toString() => "ArrayDataHeader($size, $numElements)";
44 }
45
46 class MojoCodecError {
47 final String message;
48 MojoCodecError(this.message);
49 String toString() => message;
50 }
51
52 class _EncoderBuffer {
53 ByteData buffer;
54 List<core.MojoHandle> handles;
55 int extent;
56
57 static const int kInitialBufferSize = 1024;
58
59 _EncoderBuffer([int size = -1])
60 : buffer = new ByteData(size > 0 ? size : kInitialBufferSize),
61 handles = [],
62 extent = 0;
63
64 void _grow(int newSize) {
65 Uint8List newBuffer = new Uint8List(newSize);
66 newBuffer.setRange(0, buffer.lengthInBytes, buffer.buffer.asUint8List());
67 buffer = newBuffer.buffer.asByteData();
68 }
69
70 void claimMemory(int claimSize) {
71 extent += claimSize;
72 if (extent > buffer.lengthInBytes) {
73 int newSize = buffer.lengthInBytes + claimSize;
74 newSize += newSize ~/ 2;
75 _grow(newSize);
76 }
77 }
78
79 ByteData get trimmed => new ByteData.view(buffer.buffer, 0, extent);
80 }
81
82 class Encoder {
83 _EncoderBuffer _buffer;
84 int _base;
85
86 Encoder([int size = -1])
87 : _buffer = new _EncoderBuffer(size),
88 _base = 0;
89
90 Encoder._fromBuffer(_EncoderBuffer buffer)
91 : _buffer = buffer,
92 _base = buffer.extent;
93
94 Encoder getStructEncoderAtOffset(StructDataHeader dataHeader) {
95 var result = new Encoder._fromBuffer(_buffer);
96 result.encodeStructDataHeader(dataHeader);
97 return result;
98 }
99
100 Encoder getArrayEncoderAtOffset(ArrayDataHeader dataHeader) {
101 var result = new Encoder._fromBuffer(_buffer);
102 result.encodeArrayDataHeader(dataHeader);
103 return result;
104 }
105
106 Message get message => new Message(_buffer.trimmed, _buffer.handles);
107
108 void encodeStructDataHeader(StructDataHeader dataHeader) {
109 _buffer.claimMemory(align(dataHeader.size));
110 encodeUint32(dataHeader.size, StructDataHeader.kSizeOffset);
111 encodeUint32(dataHeader.version, StructDataHeader.kVersionOffset);
112 }
113
114 void encodeArrayDataHeader(ArrayDataHeader dataHeader) {
115 _buffer.claimMemory(align(dataHeader.size));
116 encodeUint32(dataHeader.size, ArrayDataHeader.kSizeOffset);
117 encodeUint32(dataHeader.numElements, ArrayDataHeader.kNumElementsOffset);
118 }
119
120 static const String kErrorUnsigned =
121 'Passing negative value to unsigned encoder';
122
123 void encodeBool(bool value, int offset, int bit) {
124 if (value) {
125 int encodedValue = _buffer.buffer.getUint8(_base + offset);
126 encodedValue |= (1 << bit);
127 _buffer.buffer.setUint8(_base + offset, encodedValue);
128 }
129 }
130
131 void encodeInt8(int value, int offset) =>
132 _buffer.buffer.setInt8(_base + offset, value);
133
134 void encodeUint8(int value, int offset) {
135 if (value < 0) {
136 throw new MojoCodecError('$kErrorUnsigned: $value');
137 }
138 _buffer.buffer.setUint8(_base + offset, value);
139 }
140
141 void encodeInt16(int value, int offset) =>
142 _buffer.buffer.setInt16(_base + offset, value, Endianness.LITTLE_ENDIAN);
143
144 void encodeUint16(int value, int offset) {
145 if (value < 0) {
146 throw new MojoCodecError('$kErrorUnsigned: $value');
147 }
148 _buffer.buffer.setUint16(_base + offset, value, Endianness.LITTLE_ENDIAN);
149 }
150
151 void encodeInt32(int value, int offset) =>
152 _buffer.buffer.setInt32(_base + offset, value, Endianness.LITTLE_ENDIAN);
153
154 void encodeUint32(int value, int offset) {
155 if (value < 0) {
156 throw new MojoCodecError('$kErrorUnsigned: $value');
157 }
158 _buffer.buffer.setUint32(_base + offset, value, Endianness.LITTLE_ENDIAN);
159 }
160
161 void encodeInt64(int value, int offset) =>
162 _buffer.buffer.setInt64(_base + offset, value, Endianness.LITTLE_ENDIAN);
163
164 void encodeUint64(int value, int offset) {
165 if (value < 0) {
166 throw new MojoCodecError('$kErrorUnsigned: $value');
167 }
168 _buffer.buffer.setUint64(_base + offset, value, Endianness.LITTLE_ENDIAN);
169 }
170
171 void encodeFloat(double value, int offset) => _buffer.buffer.setFloat32(
172 _base + offset, value, Endianness.LITTLE_ENDIAN);
173
174 void encodeDouble(double value, int offset) => _buffer.buffer.setFloat64(
175 _base + offset, value, Endianness.LITTLE_ENDIAN);
176
177 void encodeHandle(core.MojoHandle value, int offset, bool nullable) {
178 if ((value == null) || !value.isValid) {
179 encodeInvalideHandle(offset, nullable);
180 } else {
181 encodeUint32(_buffer.handles.length, offset);
182 _buffer.handles.add(value.pass());
183 }
184 }
185
186 void encodeMessagePipeHandle(
187 core.MojoMessagePipeEndpoint value, int offset, bool nullable) =>
188 encodeHandle(value != null ? value.handle : null, offset, nullable);
189
190 void encodeConsumerHandle(
191 core.MojoDataPipeConsumer value, int offset, bool nullable) =>
192 encodeHandle(value != null ? value.handle : null, offset, nullable);
193
194 void encodeProducerHandle(
195 core.MojoDataPipeProducer value, int offset, bool nullable) =>
196 encodeHandle(value != null ? value.handle : null, offset, nullable);
197
198 void encodeSharedBufferHandle(
199 core.MojoSharedBuffer value, int offset, bool nullable) =>
200 encodeHandle(value != null ? value.handle : null, offset, nullable);
201
202 void encodeInterface(
203 core.MojoEventStreamListener interface, int offset, bool nullable) {
204 if (interface == null) {
205 encodeInvalideHandle(offset, nullable);
206 // Set the version field to 0.
207 encodeUint32(0, offset + kSerializedHandleSize);
208 return;
209 }
210 if (interface is Stub) {
211 assert(!interface.isBound);
212 var pipe = new core.MojoMessagePipe();
213 interface.bind(pipe.endpoints[0]);
214 interface.listen();
215 encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable);
216 // Set the version to the version in the stub.
217 encodeUint32(interface.version, offset + kSerializedHandleSize);
218 } else if (interface is Proxy) {
219 assert(interface.isBound);
220 if (!interface.isOpen) {
221 // Make sure that we are listening so that state for the proxy is
222 // cleaned up when the message is sent and the handle is closed.
223 interface.listen();
224 }
225 encodeMessagePipeHandle(interface.endpoint, offset, nullable);
226 // Set the version to the current version of the proxy.
227 encodeUint32(interface.version, offset + kSerializedHandleSize);
228 } else {
229 throw new MojoCodecError(
230 'Trying to encode an unknown MojoEventStreamListener');
231 }
232 }
233
234 void encodeInterfaceRequest(ProxyBase client, int offset, bool nullable) {
235 if (client == null) {
236 encodeInvalideHandle(offset, nullable);
237 return;
238 }
239 var pipe = new core.MojoMessagePipe();
240 client.impl.bind(pipe.endpoints[0]);
241 client.impl.listen();
242 encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable);
243 }
244
245 void encodeNullPointer(int offset, bool nullable) {
246 if (!nullable) {
247 throw new MojoCodecError(
248 'Trying to encode a null pointer for a non-nullable type');
249 }
250 _buffer.buffer.setUint64(_base + offset, 0, Endianness.LITTLE_ENDIAN);
251 }
252
253 void encodeInvalideHandle(int offset, bool nullable) {
254 if (!nullable) {
255 throw new MojoCodecError(
256 'Trying to encode a null pointer for a non-nullable type');
257 }
258 _buffer.buffer.setInt32(_base + offset, -1, Endianness.LITTLE_ENDIAN);
259 }
260
261 void encodePointerToNextUnclaimed(int offset) =>
262 encodeUint64(_buffer.extent - (_base + offset), offset);
263
264 void encodeStruct(Struct value, int offset, bool nullable) {
265 if (value == null) {
266 encodeNullPointer(offset, nullable);
267 return;
268 }
269 encodePointerToNextUnclaimed(offset);
270 value.encode(this);
271 }
272
273 Encoder encodePointerArray(int length, int offset, int expectedLength) =>
274 encoderForArray(kPointerSize, length, offset, expectedLength);
275
276 Encoder encoderForArray(
277 int elementSize, int length, int offset, int expectedLength) {
278 if ((expectedLength != kUnspecifiedArrayLength) &&
279 (expectedLength != length)) {
280 throw new MojoCodecError(
281 'Trying to encode a fixed array of incorrect length');
282 }
283 return encoderForArrayByTotalSize(length * elementSize, length, offset);
284 }
285
286 Encoder encoderForArrayByTotalSize(int size, int length, int offset) {
287 encodePointerToNextUnclaimed(offset);
288 return getArrayEncoderAtOffset(
289 new ArrayDataHeader(ArrayDataHeader.kHeaderSize + size, length));
290 }
291
292 void encodeBoolArray(
293 List<bool> value, int offset, int nullability, int expectedLength) {
294 if (value == null) {
295 encodeNullPointer(offset, isArrayNullable(nullability));
296 return;
297 }
298 if ((expectedLength != kUnspecifiedArrayLength) &&
299 (expectedLength != value.length)) {
300 throw new MojoCodecError(
301 'Trying to encode a fixed array of incorrect size.');
302 }
303 var bytes = new Uint8List((value.length + 7) ~/ kAlignment);
304 for (int i = 0; i < bytes.length; ++i) {
305 for (int j = 0; j < kAlignment; ++j) {
306 int boolIndex = kAlignment * i + j;
307 if ((boolIndex < value.length) && value[boolIndex]) {
308 bytes[i] |= (1 << j);
309 }
310 }
311 }
312 var encoder =
313 encoderForArrayByTotalSize(bytes.length, value.length, offset);
314 encoder.appendUint8Array(bytes);
315 }
316
317 void encodeArray(Function arrayAppend, int elementBytes, List<int> value,
318 int offset, int nullability, int expectedLength) {
319 if (value == null) {
320 encodeNullPointer(offset, isArrayNullable(nullability));
321 return;
322 }
323 var encoder =
324 encoderForArray(elementBytes, value.length, offset, expectedLength);
325 arrayAppend(encoder, value);
326 }
327
328 void encodeInt8Array(
329 List<int> value, int offset, int nullability, int expectedLength) =>
330 encodeArray((e, v) => e.appendInt8Array(v), 1, value, offset, nullability,
331 expectedLength);
332
333 void encodeUint8Array(
334 List<int> value, int offset, int nullability, int expectedLength) =>
335 encodeArray((e, v) => e.appendUint8Array(v), 1, value, offset,
336 nullability, expectedLength);
337
338 void encodeInt16Array(
339 List<int> value, int offset, int nullability, int expectedLength) =>
340 encodeArray((e, v) => e.appendInt16Array(v), 2, value, offset,
341 nullability, expectedLength);
342
343 void encodeUint16Array(
344 List<int> value, int offset, int nullability, int expectedLength) =>
345 encodeArray((e, v) => e.appendUint16Array(v), 2, value, offset,
346 nullability, expectedLength);
347
348 void encodeInt32Array(
349 List<int> value, int offset, int nullability, int expectedLength) =>
350 encodeArray((e, v) => e.appendInt32Array(v), 4, value, offset,
351 nullability, expectedLength);
352
353 void encodeUint32Array(
354 List<int> value, int offset, int nullability, int expectedLength) =>
355 encodeArray((e, v) => e.appendUint32Array(v), 4, value, offset,
356 nullability, expectedLength);
357
358 void encodeInt64Array(
359 List<int> value, int offset, int nullability, int expectedLength) =>
360 encodeArray((e, v) => e.appendInt64Array(v), 8, value, offset,
361 nullability, expectedLength);
362
363 void encodeUint64Array(
364 List<int> value, int offset, int nullability, int expectedLength) =>
365 encodeArray((e, v) => e.appendUint64Array(v), 8, value, offset,
366 nullability, expectedLength);
367
368 void encodeFloatArray(
369 List<int> value, int offset, int nullability, int expectedLength) =>
370 encodeArray((e, v) => e.appendFloatArray(v), 4, value, offset,
371 nullability, expectedLength);
372
373 void encodeDoubleArray(
374 List<int> value, int offset, int nullability, int expectedLength) =>
375 encodeArray((e, v) => e.appendDoubleArray(v), 8, value, offset,
376 nullability, expectedLength);
377
378 void _handleArrayEncodeHelper(Function elementEncoder, List value, int offset,
379 int elementSize, int nullability, int expectedLength) {
380 if (value == null) {
381 encodeNullPointer(offset, isArrayNullable(nullability));
382 return;
383 }
384 var encoder =
385 encoderForArray(elementSize, value.length, offset, expectedLength);
386 for (int i = 0; i < value.length; ++i) {
387 int elementOffset = ArrayDataHeader.kHeaderSize + elementSize * i;
388 elementEncoder(
389 encoder, value[i], elementOffset, isElementNullable(nullability));
390 }
391 }
392
393 void encodeHandleArray(List<core.MojoHandle> value, int offset,
394 int nullability, int expectedLength) => _handleArrayEncodeHelper(
395 (e, v, o, n) => e.encodeHandle(v, o, n), value, offset,
396 kSerializedHandleSize, nullability, expectedLength);
397
398 void encodeMessagePipeHandleArray(List<core.MojoMessagePipeEndpoint> value,
399 int offset, int nullability, int expectedLength) =>
400 _handleArrayEncodeHelper(
401 (e, v, o, n) => e.encodeMessagePipeHandle(v, o, n), value, offset,
402 kSerializedHandleSize, nullability, expectedLength);
403
404 void encodeConsumerHandleArray(List<core.MojoDataPipeConsumer> value,
405 int offset, int nullability, int expectedLength) =>
406 _handleArrayEncodeHelper((e, v, o, n) => e.encodeConsumerHandle(v, o, n),
407 value, offset, kSerializedHandleSize, nullability, expectedLength);
408
409 void encodeProducerHandleArray(List<core.MojoDataPipeProducer> value,
410 int offset, int nullability, int expectedLength) =>
411 _handleArrayEncodeHelper((e, v, o, n) => e.encodeProducerHandle(v, o, n),
412 value, offset, kSerializedHandleSize, nullability, expectedLength);
413
414 void encodeSharedBufferHandleArray(List<core.MojoSharedBuffer> value,
415 int offset, int nullability, int expectedLength) =>
416 _handleArrayEncodeHelper(
417 (e, v, o, n) => e.encodeSharedBufferHandle(v, o, n), value, offset,
418 kSerializedHandleSize, nullability, expectedLength);
419
420 void encodeInterfaceRequestArray(
421 List<Proxy> value, int offset, int nullability, int expectedLength) =>
422 _handleArrayEncodeHelper(
423 (e, v, o, n) => e.encodeInterfaceRequest(v, o, n), value, offset,
424 kSerializedHandleSize, nullability, expectedLength);
425
426 void encodeInterfaceArray(
427 List<Stub> value, int offset, int nullability, int expectedLength) =>
428 _handleArrayEncodeHelper((e, v, o, n) => e.encodeInterface(v, o, n),
429 value, offset, kSerializedInterfaceSize, nullability, expectedLength);
430
431 static Uint8List _utf8OfString(String s) =>
432 (new Uint8List.fromList((const Utf8Encoder()).convert(s)));
433
434 void encodeString(String value, int offset, bool nullable) {
435 if (value == null) {
436 encodeNullPointer(offset, nullable);
437 return;
438 }
439 int nullability = nullable ? kArrayNullable : kNothingNullable;
440 encodeUint8Array(
441 _utf8OfString(value), offset, nullability, kUnspecifiedArrayLength);
442 }
443
444 void appendBytes(Uint8List value) {
445 _buffer.buffer.buffer
446 .asUint8List()
447 .setRange(_base + ArrayDataHeader.kHeaderSize,
448 _base + ArrayDataHeader.kHeaderSize + value.lengthInBytes, value);
449 }
450
451 void appendInt8Array(List<int> value) =>
452 appendBytes(new Uint8List.view(new Int8List.fromList(value).buffer));
453
454 void appendUint8Array(List<int> value) =>
455 appendBytes(new Uint8List.fromList(value));
456
457 void appendInt16Array(List<int> value) =>
458 appendBytes(new Uint8List.view(new Int16List.fromList(value).buffer));
459
460 void appendUint16Array(List<int> value) =>
461 appendBytes(new Uint8List.view(new Uint16List.fromList(value).buffer));
462
463 void appendInt32Array(List<int> value) =>
464 appendBytes(new Uint8List.view(new Int32List.fromList(value).buffer));
465
466 void appendUint32Array(List<int> value) =>
467 appendBytes(new Uint8List.view(new Uint32List.fromList(value).buffer));
468
469 void appendInt64Array(List<int> value) =>
470 appendBytes(new Uint8List.view(new Int64List.fromList(value).buffer));
471
472 void appendUint64Array(List<int> value) =>
473 appendBytes(new Uint8List.view(new Uint64List.fromList(value).buffer));
474
475 void appendFloatArray(List<double> value) =>
476 appendBytes(new Uint8List.view(new Float32List.fromList(value).buffer));
477
478 void appendDoubleArray(List<double> value) =>
479 appendBytes(new Uint8List.view(new Float64List.fromList(value).buffer));
480
481 Encoder encoderForMap(int offset) {
482 encodePointerToNextUnclaimed(offset);
483 return getStructEncoderAtOffset(kMapStructHeader);
484 }
485 }
486
487 class _Validator {
488 final int _maxMemory;
489 final int _numberOfHandles;
490 int _minNextClaimedHandle = 0;
491 int _minNextMemory = 0;
492 List<int> _skippedIndices = [];
493
494 _Validator(this._maxMemory, this._numberOfHandles);
495
496 void claimHandle(int handle) {
497 if (handle < _minNextClaimedHandle) {
498 throw new MojoCodecError('Trying to access handle out of order.');
499 }
500 if (handle >= _numberOfHandles) {
501 throw new MojoCodecError('Trying to access non present handle.');
502 }
503 for (int i = _minNextClaimedHandle; i < handle; i++) {
504 _skippedIndices.add(i);
505 }
506 _minNextClaimedHandle = handle + 1;
507 }
508
509 void claimMemory(int start, int end) {
510 if ((start % kAlignment) != 0) {
511 throw new MojoCodecError('Incorrect starting alignment: $start.');
512 }
513 if (start < _minNextMemory) {
514 throw new MojoCodecError('Trying to access memory out of order.');
515 }
516 if (end < start) {
517 throw new MojoCodecError('Incorrect memory range.');
518 }
519 if (end > _maxMemory) {
520 throw new MojoCodecError('Trying to access out of range memory.');
521 }
522 _minNextMemory = align(end);
523 }
524 }
525
526 class Decoder {
527 _Validator _validator;
528 Message _message;
529 int _base = 0;
530
531 Decoder(this._message, [this._base = 0, this._validator = null]) {
532 if (_validator == null) {
533 _validator = new _Validator(
534 _message.buffer.lengthInBytes, _message.handles.length);
535 }
536 }
537
538 Decoder getDecoderAtPosition(int offset) =>
539 new Decoder(_message, offset, _validator);
540
541 factory Decoder.atOffset(Decoder d, int offset, _Validator validator) =>
542 new Decoder(d._message, offset, validator);
543
544 ByteData get _buffer => _message.buffer;
545 List<core.MojoHandle> get _handles => _message.handles;
546 List<core.MojoHandle> get excessHandles => new List.from(_message.handles
547 .getRange(_validator._minNextClaimedHandle, _message.handles.length))
548 ..addAll(_validator._skippedIndices.map((i) => _message.handles[i]));
549
550 int decodeInt8(int offset) => _buffer.getInt8(_base + offset);
551 int decodeUint8(int offset) => _buffer.getUint8(_base + offset);
552 int decodeInt16(int offset) =>
553 _buffer.getInt16(_base + offset, Endianness.LITTLE_ENDIAN);
554 int decodeUint16(int offset) =>
555 _buffer.getUint16(_base + offset, Endianness.LITTLE_ENDIAN);
556 int decodeInt32(int offset) =>
557 _buffer.getInt32(_base + offset, Endianness.LITTLE_ENDIAN);
558 int decodeUint32(int offset) =>
559 _buffer.getUint32(_base + offset, Endianness.LITTLE_ENDIAN);
560 int decodeInt64(int offset) =>
561 _buffer.getInt64(_base + offset, Endianness.LITTLE_ENDIAN);
562 int decodeUint64(int offset) =>
563 _buffer.getUint64(_base + offset, Endianness.LITTLE_ENDIAN);
564 double decodeFloat(int offset) =>
565 _buffer.getFloat32(_base + offset, Endianness.LITTLE_ENDIAN);
566 double decodeDouble(int offset) =>
567 _buffer.getFloat64(_base + offset, Endianness.LITTLE_ENDIAN);
568
569 bool decodeBool(int offset, int bit) =>
570 (decodeUint8(offset) & (1 << bit)) != 0;
571
572 core.MojoHandle decodeHandle(int offset, bool nullable) {
573 int index = decodeInt32(offset);
574 if (index == -1) {
575 if (!nullable) {
576 throw new MojoCodecError(
577 'Trying to decode an invalid handle from a non-nullable type.');
578 }
579 return new core.MojoHandle.invalid();
580 }
581 _validator.claimHandle(index);
582 return _handles[index];
583 }
584
585 core.MojoMessagePipeEndpoint decodeMessagePipeHandle(
586 int offset, bool nullable) =>
587 new core.MojoMessagePipeEndpoint(decodeHandle(offset, nullable));
588
589 core.MojoDataPipeConsumer decodeConsumerHandle(int offset, bool nullable) =>
590 new core.MojoDataPipeConsumer(decodeHandle(offset, nullable));
591
592 core.MojoDataPipeProducer decodeProducerHandle(int offset, bool nullable) =>
593 new core.MojoDataPipeProducer(decodeHandle(offset, nullable));
594
595 core.MojoSharedBuffer decodeSharedBufferHandle(int offset, bool nullable) =>
596 new core.MojoSharedBuffer(decodeHandle(offset, nullable));
597
598 ProxyBase decodeServiceInterface(
599 int offset, bool nullable, Function clientFactory) {
600 var endpoint = decodeMessagePipeHandle(offset, nullable);
601 var version = decodeUint32(offset + kSerializedHandleSize);
602 if (!endpoint.handle.isValid) {
603 return null;
604 }
605 ProxyBase client = clientFactory(endpoint);
606 client.impl._version = version;
607 return client;
608 }
609
610 Stub decodeInterfaceRequest(
611 int offset, bool nullable, Function interfaceFactory) {
612 var endpoint = decodeMessagePipeHandle(offset, nullable);
613 return endpoint.handle.isValid ? interfaceFactory(endpoint) : null;
614 }
615
616 Decoder decodePointer(int offset, bool nullable) {
617 int basePosition = _base + offset;
618 int pointerOffset = decodeUint64(offset);
619 if (pointerOffset == 0) {
620 if (!nullable) {
621 throw new MojoCodecError(
622 'Trying to decode a null pointer for a non-nullable type');
623 }
624 return null;
625 }
626 int newPosition = (basePosition + pointerOffset);
627 return new Decoder.atOffset(this, newPosition, _validator);
628 }
629
630 StructDataHeader decodeStructDataHeader() {
631 _validator.claimMemory(_base, _base + StructDataHeader.kHeaderSize);
632 int size = decodeUint32(StructDataHeader.kSizeOffset);
633 int version = decodeUint32(StructDataHeader.kVersionOffset);
634 if (size < 0) {
635 throw new MojoCodecError('Negative size.');
636 }
637 if (version < 0) {
638 throw new MojoCodecError('Negative version number.');
639 }
640 _validator.claimMemory(_base + StructDataHeader.kHeaderSize, _base + size);
641 return new StructDataHeader(size, version);
642 }
643
644 ArrayDataHeader decodeArrayDataHeader() {
645 _validator.claimMemory(_base, _base + ArrayDataHeader.kHeaderSize);
646 int size = decodeUint32(ArrayDataHeader.kSizeOffset);
647 int numElements = decodeUint32(ArrayDataHeader.kNumElementsOffset);
648 if (size < 0) {
649 throw new MojoCodecError('Negative size.');
650 }
651 if (numElements < 0) {
652 throw new MojoCodecError('Negative number of elements.');
653 }
654 _validator.claimMemory(_base + ArrayDataHeader.kHeaderSize, _base + size);
655 return new ArrayDataHeader(size, numElements);
656 }
657
658 // Decode arrays.
659 ArrayDataHeader decodeDataHeaderForBoolArray(int expectedLength) {
660 var header = decodeArrayDataHeader();
661 var arrayByteCount =
662 ArrayDataHeader.kHeaderSize + (header.numElements + 7) ~/ 8;
663 if (header.size < arrayByteCount) {
664 throw new MojoCodecError('Array header is incorrect');
665 }
666 if ((expectedLength != kUnspecifiedArrayLength) &&
667 (header.numElements != expectedLength)) {
668 throw new MojoCodecError(
669 'Incorrect array length. Expected $expectedLength, but got '
670 '${header.numElements}.');
671 }
672 return header;
673 }
674
675 List<bool> decodeBoolArray(int offset, int nullability, int expectedLength) {
676 Decoder d = decodePointer(offset, isArrayNullable(nullability));
677 if (d == null) {
678 return null;
679 }
680 var header = d.decodeDataHeaderForBoolArray(expectedLength);
681 var bytes = new Uint8List.view(d._buffer.buffer,
682 d._buffer.offsetInBytes + d._base + ArrayDataHeader.kHeaderSize,
683 (header.numElements + 7) ~/ kAlignment);
684 var result = new List<bool>(header.numElements);
685 for (int i = 0; i < bytes.lengthInBytes; ++i) {
686 for (int j = 0; j < kAlignment; ++j) {
687 int boolIndex = i * kAlignment + j;
688 if (boolIndex < result.length) {
689 result[boolIndex] = (bytes[i] & (1 << j)) != 0;
690 }
691 }
692 }
693 return result;
694 }
695
696 ArrayDataHeader decodeDataHeaderForArray(
697 int elementSize, int expectedLength) {
698 var header = decodeArrayDataHeader();
699 var arrayByteCount =
700 ArrayDataHeader.kHeaderSize + header.numElements * elementSize;
701 if (header.size < arrayByteCount) {
702 throw new MojoCodecError(
703 'Array header is incorrect: $header, elementSize = $elementSize');
704 }
705 if ((expectedLength != kUnspecifiedArrayLength) &&
706 (header.numElements != expectedLength)) {
707 throw new MojoCodecError(
708 'Incorrect array length. Expected $expectedLength, but got '
709 '${header.numElements}');
710 }
711 return header;
712 }
713
714 ArrayDataHeader decodeDataHeaderForPointerArray(int expectedLength) =>
715 decodeDataHeaderForArray(kPointerSize, expectedLength);
716
717 List decodeArray(Function arrayViewer, int elementSize, int offset,
718 int nullability, int expectedLength) {
719 Decoder d = decodePointer(offset, isArrayNullable(nullability));
720 if (d == null) {
721 return null;
722 }
723 var header = d.decodeDataHeaderForArray(elementSize, expectedLength);
724 return arrayViewer(d._buffer.buffer,
725 d._buffer.offsetInBytes + d._base + ArrayDataHeader.kHeaderSize,
726 header.numElements);
727 }
728
729 List<int> decodeInt8Array(int offset, int nullability, int expectedLength) =>
730 decodeArray((b, s, l) => new Int8List.view(b, s, l), 1, offset,
731 nullability, expectedLength);
732
733 List<int> decodeUint8Array(int offset, int nullability, int expectedLength) =>
734 decodeArray((b, s, l) => new Uint8List.view(b, s, l), 1, offset,
735 nullability, expectedLength);
736
737 List<int> decodeInt16Array(int offset, int nullability, int expectedLength) =>
738 decodeArray((b, s, l) => new Int16List.view(b, s, l), 2, offset,
739 nullability, expectedLength);
740
741 List<int> decodeUint16Array(
742 int offset, int nullability, int expectedLength) => decodeArray(
743 (b, s, l) => new Uint16List.view(b, s, l), 2, offset, nullability,
744 expectedLength);
745
746 List<int> decodeInt32Array(int offset, int nullability, int expectedLength) =>
747 decodeArray((b, s, l) => new Int32List.view(b, s, l), 4, offset,
748 nullability, expectedLength);
749
750 List<int> decodeUint32Array(
751 int offset, int nullability, int expectedLength) => decodeArray(
752 (b, s, l) => new Uint32List.view(b, s, l), 4, offset, nullability,
753 expectedLength);
754
755 List<int> decodeInt64Array(int offset, int nullability, int expectedLength) =>
756 decodeArray((b, s, l) => new Int64List.view(b, s, l), 8, offset,
757 nullability, expectedLength);
758
759 List<int> decodeUint64Array(
760 int offset, int nullability, int expectedLength) => decodeArray(
761 (b, s, l) => new Uint64List.view(b, s, l), 8, offset, nullability,
762 expectedLength);
763
764 List<double> decodeFloatArray(
765 int offset, int nullability, int expectedLength) => decodeArray(
766 (b, s, l) => new Float32List.view(b, s, l), 4, offset, nullability,
767 expectedLength);
768
769 List<double> decodeDoubleArray(
770 int offset, int nullability, int expectedLength) => decodeArray(
771 (b, s, l) => new Float64List.view(b, s, l), 8, offset, nullability,
772 expectedLength);
773
774 List _handleArrayDecodeHelper(Function elementDecoder, int offset,
775 int elementSize, int nullability, int expectedLength) {
776 Decoder d = decodePointer(offset, isArrayNullable(nullability));
777 if (d == null) {
778 return null;
779 }
780 var header = d.decodeDataHeaderForArray(elementSize, expectedLength);
781 var result = new List(header.numElements);
782 for (int i = 0; i < result.length; ++i) {
783 result[i] = elementDecoder(d,
784 ArrayDataHeader.kHeaderSize + elementSize * i,
785 isElementNullable(nullability));
786 }
787 return result;
788 }
789
790 List<core.MojoHandle> decodeHandleArray(
791 int offset, int nullability, int expectedLength) =>
792 _handleArrayDecodeHelper((d, o, n) => d.decodeHandle(o, n), offset,
793 kSerializedHandleSize, nullability, expectedLength);
794
795 List<core.MojoDataPipeConsumer> decodeConsumerHandleArray(
796 int offset, int nullability, int expectedLength) =>
797 _handleArrayDecodeHelper((d, o, n) => d.decodeConsumerHandle(o, n),
798 offset, kSerializedHandleSize, nullability, expectedLength);
799
800 List<core.MojoDataPipeProducer> decodeProducerHandleArray(
801 int offset, int nullability, int expectedLength) =>
802 _handleArrayDecodeHelper((d, o, n) => d.decodeProducerHandle(o, n),
803 offset, kSerializedHandleSize, nullability, expectedLength);
804
805 List<core.MojoMessagePipeEndpoint> decodeMessagePipeHandleArray(
806 int offset, int nullability, int expectedLength) =>
807 _handleArrayDecodeHelper((d, o, n) => d.decodeMessagePipeHandle(o, n),
808 offset, kSerializedHandleSize, nullability, expectedLength);
809
810 List<core.MojoSharedBuffer> decodeSharedBufferHandleArray(
811 int offset, int nullability, int expectedLength) =>
812 _handleArrayDecodeHelper((d, o, n) => d.decodeSharedBufferHandle(o, n),
813 offset, kSerializedHandleSize, nullability, expectedLength);
814
815 List<Stub> decodeInterfaceRequestArray(int offset, int nullability,
816 int expectedLength, Function interfaceFactory) =>
817 _handleArrayDecodeHelper(
818 (d, o, n) => d.decodeInterfaceRequest(o, n, interfaceFactory), offset,
819 kSerializedHandleSize, nullability, expectedLength);
820
821 List<Proxy> decodeServiceInterfaceArray(int offset, int nullability,
822 int expectedLength, Function clientFactory) => _handleArrayDecodeHelper(
823 (d, o, n) => d.decodeServiceInterface(o, n, clientFactory), offset,
824 kSerializedInterfaceSize, nullability, expectedLength);
825
826 static String _stringOfUtf8(Uint8List bytes) =>
827 (const Utf8Decoder()).convert(bytes.toList());
828
829 String decodeString(int offset, bool nullable) {
830 int nullability = nullable ? kArrayNullable : 0;
831 var bytes = decodeUint8Array(offset, nullability, kUnspecifiedArrayLength);
832 if (bytes == null) {
833 return null;
834 }
835 return _stringOfUtf8(bytes);
836 }
837
838 StructDataHeader decodeDataHeaderForMap() {
839 var header = decodeStructDataHeader();
840 if (header.size != kMapStructHeader.size) {
841 throw new MojoCodecError(
842 'Incorrect header for map. The size is incorrect.');
843 }
844 if (header.version != kMapStructHeader.version) {
845 throw new MojoCodecError(
846 'Incorrect header for map. The version is incorrect.');
847 }
848 return header;
849 }
850 }
OLDNEW
« no previous file with comments | « mojo/public/dart/src/buffer.dart ('k') | mojo/public/dart/src/control_message.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698