OLD | NEW |
| (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 kPointerSize = 8; | |
12 const DataHeader kMapStructHeader = const DataHeader(24, 2); | |
13 const int kUnspecifiedArrayLength = -1; | |
14 const int kNothingNullable = 0; | |
15 const int kArrayNullable = (1 << 0); | |
16 const int kElementNullable = (1 << 1); | |
17 | |
18 bool isArrayNullable(int nullability) => (nullability & kArrayNullable) > 0; | |
19 bool isElementNullable(int nullability) => (nullability & kElementNullable) > 0; | |
20 | |
21 class _EncoderBuffer { | |
22 ByteData buffer; | |
23 List<core.MojoHandle> handles; | |
24 int extent; | |
25 | |
26 static const int kInitialBufferSize = 1024; | |
27 | |
28 _EncoderBuffer([int size = -1]) : | |
29 buffer = new ByteData(size > 0 ? size : kInitialBufferSize), | |
30 handles = [], | |
31 extent = 0; | |
32 | |
33 void _grow(int newSize) { | |
34 Uint8List newBuffer = new Uint8List(newSize); | |
35 newBuffer.setRange(0, buffer.lengthInBytes, buffer.buffer.asUint8List()); | |
36 buffer = newBuffer.buffer.asByteData(); | |
37 } | |
38 | |
39 void claimMemory(int claimSize) { | |
40 extent += claimSize; | |
41 if (extent > buffer.lengthInBytes) { | |
42 int newSize = buffer.lengthInBytes + claimSize; | |
43 newSize += newSize ~/ 2; | |
44 _grow(newSize); | |
45 } | |
46 } | |
47 | |
48 ByteData get trimmed => new ByteData.view(buffer.buffer, 0, extent); | |
49 } | |
50 | |
51 class Encoder { | |
52 _EncoderBuffer _buffer; | |
53 int _base; | |
54 | |
55 Encoder([int size = -1]) : _buffer = new _EncoderBuffer(size), _base = 0; | |
56 | |
57 Encoder._fromBuffer(_EncoderBuffer buffer) : | |
58 _buffer = buffer, | |
59 _base = buffer.extent; | |
60 | |
61 Encoder getEncoderAtOffset(DataHeader dataHeader) { | |
62 var result = new Encoder._fromBuffer(_buffer); | |
63 result.encodeDataHeader(dataHeader); | |
64 return result; | |
65 } | |
66 | |
67 Message get message => new Message(_buffer.trimmed, _buffer.handles); | |
68 | |
69 void encodeDataHeader(DataHeader dataHeader) { | |
70 _buffer.claimMemory(align(dataHeader.size)); | |
71 encodeUint32(dataHeader.size, DataHeader.kSizeOffset); | |
72 encodeUint32(dataHeader.numFields, DataHeader.kNumFieldsOffset); | |
73 } | |
74 | |
75 static const String kErrorUnsigned = | |
76 'Passing negative value to unsigned encoder'; | |
77 | |
78 void encodeBool(bool value, int offset, int bit) { | |
79 if (value) { | |
80 int encodedValue = _buffer.buffer.getUint8(_base + offset); | |
81 encodedValue |= (1 << bit); | |
82 _buffer.buffer.setUint8(_base + offset, encodedValue); | |
83 } | |
84 } | |
85 | |
86 void encodeInt8(int value, int offset) => | |
87 _buffer.buffer.setInt8(_base + offset, value); | |
88 | |
89 void encodeUint8(int value, int offset) { | |
90 if (value < 0) { | |
91 throw '$kErrorUnsigned: $val'; | |
92 } | |
93 _buffer.buffer.setUint8(_base + offset, value); | |
94 } | |
95 | |
96 void encodeInt16(int value, int offset) => | |
97 _buffer.buffer.setInt16(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
98 | |
99 void encodeUint16(int value, int offset) { | |
100 if (value < 0) { | |
101 throw '$kErrorUnsigned: $val'; | |
102 } | |
103 _buffer.buffer.setUint16(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
104 } | |
105 | |
106 void encodeInt32(int value, int offset) => | |
107 _buffer.buffer.setInt32(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
108 | |
109 void encodeUint32(int value, int offset) { | |
110 if (value < 0) { | |
111 throw '$kErrorUnsigned: $val'; | |
112 } | |
113 _buffer.buffer.setUint32(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
114 } | |
115 | |
116 void encodeInt64(int value, int offset) => | |
117 _buffer.buffer.setInt64(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
118 | |
119 void encodeUint64(int value, int offset) { | |
120 if (value < 0) { | |
121 throw '$kErrorUnsigned: $val'; | |
122 } | |
123 _buffer.buffer.setUint64(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
124 } | |
125 | |
126 void encodeFloat(double value, int offset) => | |
127 _buffer.buffer.setFloat32(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
128 | |
129 void encodeDouble(double value, int offset) => | |
130 _buffer.buffer.setFloat64(_base + offset, value, Endianness.LITTLE_ENDIAN); | |
131 | |
132 void encodeHandle(core.MojoHandle value, int offset, bool nullable) { | |
133 if ((value == null) || !value.isValid) { | |
134 encodeInvalideHandle(offset, nullable); | |
135 } else { | |
136 encodeUint32(_buffer.handles.length, offset); | |
137 _buffer.handles.add(value); | |
138 } | |
139 } | |
140 | |
141 void encodeMessagePipeHandle( | |
142 core.MojoMessagePipeEndpoint value, int offset, bool nullable) => | |
143 encodeHandle(value != null ? value.handle : null, offset, nullable); | |
144 | |
145 void encodeConsumerHandle( | |
146 core.MojoDataPipeConsumer value, int offset, bool nullable) => | |
147 encodeHandle(value != null ? value.handle : null, offset, nullable); | |
148 | |
149 void encodeProducerHandle( | |
150 core.MojoDataPipeProducer value, int offset, bool nullable) => | |
151 encodeHandle(value != null ? value.handle : null, offset, nullable); | |
152 | |
153 void encodeSharedBufferHandle( | |
154 core.MojoSharedBuffer value, int offset, bool nullable) => | |
155 encodeHandle(value != null ? value.handle : null, offset, nullable); | |
156 | |
157 void encodeInterface(Interface interface, int offset, bool nullable) { | |
158 if (interface == null) { | |
159 encodeInvalideHandle(offset, nullable); | |
160 return; | |
161 } | |
162 var pipe = new core.MojoMessagePipe(); | |
163 interface.bind(pipe.endpoints[0]); | |
164 encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable); | |
165 } | |
166 | |
167 void encodeInterfaceRequest(Client client, int offset, bool nullable) { | |
168 if (client == null) { | |
169 encodeInvalideHandle(offset, nullable); | |
170 return; | |
171 } | |
172 var pipe = new core.MojoMessagePipe(); | |
173 client.bind(pipe.endpoints[0]); | |
174 encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable); | |
175 } | |
176 | |
177 void encodeNullPointer(int offset, bool nullable) { | |
178 if (!nullable) { | |
179 throw 'Trying to encode a null pointer for a non-nullable type'; | |
180 } | |
181 _buffer.buffer.setUint64(_base + offset, 0, Endianness.LITTLE_ENDIAN); | |
182 } | |
183 | |
184 void encodeInvalideHandle(int offset, bool nullable) { | |
185 if (!nullable) { | |
186 throw 'Trying to encode a null pointer for a non-nullable type'; | |
187 } | |
188 _buffer.buffer.setInt32(_base + offset, -1, Endianness.LITTLE_ENDIAN); | |
189 } | |
190 | |
191 void encodePointerToNextUnclaimed(int offset) => | |
192 encodeUint64(_buffer.extent - (_base + offset), offset); | |
193 | |
194 void encodeStruct(Struct value, int offset, bool nullable) { | |
195 if (value == null) { | |
196 encodeNullPointer(offset, nullable); | |
197 return; | |
198 } | |
199 encodePointerToNextUnclaimed(offset); | |
200 value.encode(this); | |
201 } | |
202 | |
203 Encoder encodePointerArray(int length, int offset, int expectedLength) => | |
204 encoderForArray(kPointerSize, length, offset, expectedLength); | |
205 | |
206 Encoder encoderForArray( | |
207 int elementSize, int length, int offset, int expectedLength) { | |
208 if ((expectedLength != kUnspecifiedArrayLength) && | |
209 (expectedLength != length)) { | |
210 throw 'Trying to encode a fixed array of incorrect length'; | |
211 } | |
212 return encoderForArrayByTotalSize(length * elementSize, length, offset); | |
213 } | |
214 | |
215 Encoder encoderForArrayByTotalSize(int size, int length, int offset) { | |
216 encodePointerToNextUnclaimed(offset); | |
217 return getEncoderAtOffset( | |
218 new DataHeader(DataHeader.kHeaderSize + size, length)); | |
219 } | |
220 | |
221 void encodeBoolArray( | |
222 List<bool> value, int offset, int nullability, int expectedLength) { | |
223 if (value == null) { | |
224 encodeNullPointer(offset, isArrayNullable(nullability)); | |
225 return; | |
226 } | |
227 if ((expectedLength != kUnspecifiedArrayLength) && | |
228 (expectedLength != value.length)) { | |
229 throw 'Trying to encode a fixed array of incorrect size.'; | |
230 } | |
231 var bytes = new Uint8List((value.length + 7) ~/ kAlignment); | |
232 for (int i = 0; i < bytes.length; ++i) { | |
233 for (int j = 0; j < kAlignment; ++j) { | |
234 int boolIndex = kAlignment * i + j; | |
235 if ((boolIndex < value.length) && value[boolIndex]) { | |
236 bytes[i] |= (1 << j); | |
237 } | |
238 } | |
239 } | |
240 var encoder = encoderForArrayByTotalSize( | |
241 bytes.length, value.length, offset); | |
242 encoder.appendUint8Array(bytes); | |
243 } | |
244 | |
245 void encodeArray(Function arrayAppend, | |
246 int elementBytes, | |
247 List<int> value, | |
248 int offset, | |
249 int nullability, | |
250 int expectedLength) { | |
251 if (value == null) { | |
252 encodeNullPointer(offset, isArrayNullable(nullability)); | |
253 return; | |
254 } | |
255 var encoder = encoderForArray( | |
256 elementBytes, value.length, offset, expectedLength); | |
257 arrayAppend(encoder, value); | |
258 } | |
259 | |
260 void encodeInt8Array( | |
261 List<int> value, int offset, int nullability, int expectedLength) => | |
262 encodeArray((e, v) => e.appendInt8Array(v), | |
263 1, value, offset, nullability, expectedLength); | |
264 | |
265 void encodeUint8Array( | |
266 List<int> value, int offset, int nullability, int expectedLength) => | |
267 encodeArray((e, v) => e.appendUint8Array(v), | |
268 1, value, offset, nullability, expectedLength); | |
269 | |
270 void encodeInt16Array( | |
271 List<int> value, int offset, int nullability, int expectedLength) => | |
272 encodeArray((e, v) => e.appendInt16Array(v), | |
273 2, value, offset, nullability, expectedLength); | |
274 | |
275 void encodeUint16Array( | |
276 List<int> value, int offset, int nullability, int expectedLength) => | |
277 encodeArray((e, v) => e.appendUint16Array(v), | |
278 2, value, offset, nullability, expectedLength); | |
279 | |
280 void encodeInt32Array( | |
281 List<int> value, int offset, int nullability, int expectedLength) => | |
282 encodeArray((e, v) => e.appendInt32Array(v), | |
283 4, value, offset, nullability, expectedLength); | |
284 | |
285 void encodeUint32Array( | |
286 List<int> value, int offset, int nullability, int expectedLength) => | |
287 encodeArray((e, v) => e.appendUint32Array(v), | |
288 4, value, offset, nullability, expectedLength); | |
289 | |
290 void encodeInt64Array( | |
291 List<int> value, int offset, int nullability, int expectedLength) => | |
292 encodeArray((e, v) => e.appendInt64Array(v), | |
293 8, value, offset, nullability, expectedLength); | |
294 | |
295 void encodeUint64Array( | |
296 List<int> value, int offset, int nullability, int expectedLength) => | |
297 encodeArray((e, v) => e.appendUint64Array(v), | |
298 8, value, offset, nullability, expectedLength); | |
299 | |
300 void encodeFloatArray( | |
301 List<int> value, int offset, int nullability, int expectedLength) => | |
302 encodeArray((e, v) => e.appendFloatArray(v), | |
303 4, value, offset, nullability, expectedLength); | |
304 | |
305 void encodeDoubleArray( | |
306 List<int> value, int offset, int nullability, int expectedLength) => | |
307 encodeArray((e, v) => e.appendDoubleArray(v), | |
308 8, value, offset, nullability, expectedLength); | |
309 | |
310 void _handleArrayEncodeHelper(Function elementEncoder, | |
311 List value, | |
312 int offset, | |
313 int nullability, | |
314 int expectedLength) { | |
315 if (value == null) { | |
316 encodeNullPointer(offset, isArrayNullable(nullability)); | |
317 return; | |
318 } | |
319 var encoder = encoderForArray( | |
320 kSerializedHandleSize, value.length, offset, expectedLength); | |
321 for (int i = 0; i < value.length; ++i) { | |
322 int handleOffset = DataHeader.kHeaderSize + kSerializedHandleSize * i; | |
323 elementEncoder( | |
324 encoder, value[i], handleOffset, isElementNullable(nullability)); | |
325 } | |
326 } | |
327 | |
328 void encodeHandleArray( | |
329 List<core.MojoHandle> value, | |
330 int offset, | |
331 int nullability, | |
332 int expectedLength) => | |
333 _handleArrayEncodeHelper( | |
334 (e, v, o, n) => e.encodeHandle(v, o, n), | |
335 value, offset, nullability, expectedLength); | |
336 | |
337 void encodeMessagePipeHandleArray( | |
338 List<core.MojoMessagePipeEndpoint> value, | |
339 int offset, | |
340 int nullability, | |
341 int expectedLength) => | |
342 _handleArrayEncodeHelper( | |
343 (e, v, o, n) => e.encodeMessagePipeHandle(v, o, n), | |
344 value, offset, nullability, expectedLength); | |
345 | |
346 void encodeConsumerHandleArray( | |
347 List<core.MojoDataPipeConsumer> value, | |
348 int offset, | |
349 int nullability, | |
350 int expectedLength) => | |
351 _handleArrayEncodeHelper( | |
352 (e, v, o, n) => e.encodeConsumerHandle(v, o, n), | |
353 value, offset, nullability, expectedLength); | |
354 | |
355 void encodeProducerHandleArray( | |
356 List<core.MojoDataPipeProducer> value, | |
357 int offset, | |
358 int nullability, | |
359 int expectedLength) => | |
360 _handleArrayEncodeHelper( | |
361 (e, v, o, n) => e.encodeProducerHandle(v, o, n), | |
362 value, offset, nullability, expectedLength); | |
363 | |
364 void encodeSharedBufferHandleArray( | |
365 List<core.MojoSharedBuffer> value, | |
366 int offset, | |
367 int nullability, | |
368 int expectedLength) => | |
369 _handleArrayEncodeHelper( | |
370 (e, v, o, n) => e.encodeSharedBufferHandle(v, o, n), | |
371 value, offset, nullability, expectedLength); | |
372 | |
373 void encodeInterfaceRequestArray( | |
374 List<Client> value, | |
375 int offset, | |
376 int nullability, | |
377 int expectedLength) => | |
378 _handleArrayEncodeHelper( | |
379 (e, v, o, n) => e.encodeInterfaceRequest(v, o, n), | |
380 value, offset, nullability, expectedLength); | |
381 | |
382 void encodeInterfaceArray( | |
383 List<Interface> value, | |
384 int offset, | |
385 int nullability, | |
386 int expectedLength) => | |
387 _handleArrayEncodeHelper( | |
388 (e, v, o, n) => e.encodeInterface(v, o, n), | |
389 value, offset, nullability, expectedLength); | |
390 | |
391 static Uint8List _utf8OfString(String s) => | |
392 (new Uint8List.fromList((const Utf8Encoder()).convert(s))); | |
393 | |
394 void encodeString(String value, int offset, bool nullable) { | |
395 if (value == null) { | |
396 encodeNullPointer(offset, nullable); | |
397 return; | |
398 } | |
399 int nullability = nullable ? kArrayNullable : kNothingNullable; | |
400 encodeUint8Array(_utf8OfString(value), | |
401 offset, | |
402 nullability, | |
403 kUnspecifiedArrayLength); | |
404 } | |
405 | |
406 void appendBytes(Uint8List value) { | |
407 _buffer.buffer.buffer.asUint8List().setRange( | |
408 _base + DataHeader.kHeaderSize, | |
409 _base + DataHeader.kHeaderSize + value.lengthInBytes, | |
410 value); | |
411 } | |
412 | |
413 void appendInt8Array(List<int> value) => | |
414 appendBytes(new Uint8List.view(new Int8List.fromList(value))); | |
415 | |
416 void appendUint8Array(List<int> value) => | |
417 appendBytes(new Uint8List.fromList(value)); | |
418 | |
419 void appendInt16Array(List<int> value) => | |
420 appendBytes(new Uint8List.view(new Int16List.fromList(value))); | |
421 | |
422 void appendUint16Array(List<int> value) => | |
423 appendBytes(new Uint8List.view(new Uint16List.fromList(value))); | |
424 | |
425 void appendInt32Array(List<int> value) => | |
426 appendBytes(new Uint8List.view(new Int32List.fromList(value))); | |
427 | |
428 void appendUint32Array(List<int> value) => | |
429 appendBytes(new Uint8List.view(new Uint32List.fromList(value))); | |
430 | |
431 void appendInt64Array(List<int> value) => | |
432 appendBytes(new Uint8List.view(new Int64List.fromList(value))); | |
433 | |
434 void appendUint64Array(List<int> value) => | |
435 appendBytes(new Uint8List.view(new Uint64List.fromList(value))); | |
436 | |
437 void appendFloatArray(List<int> value) => | |
438 appendBytes(new Uint8List.view(new Float32List.fromList(value))); | |
439 | |
440 void appendDoubleArray(List<int> value) => | |
441 appendBytes(new Uint8List.view(new Float64List.fromList(value))); | |
442 | |
443 Encoder encoderForMap(int offset) { | |
444 encodePointerToNextUnclaimed(offset); | |
445 return getEncoderAtOffset(kMapStructHeader); | |
446 } | |
447 } | |
448 | |
449 | |
450 class Decoder { | |
451 Message _message; | |
452 int _base = 0; | |
453 | |
454 Decoder(this._message, [this._base = 0]); | |
455 | |
456 Decoder getDecoderAtPosition(int offset) => new Decoder(_message, offset); | |
457 | |
458 factory Decoder.atOffset(Decoder d, int offset) => | |
459 new Decoder(d._message, offset); | |
460 | |
461 ByteData get _buffer => _message.buffer; | |
462 List<core.MojoHandle> get _handles => _message.handles; | |
463 | |
464 int decodeInt8(int offset) => _buffer.getInt8(_base + offset); | |
465 int decodeUint8(int offset) => _buffer.getUint8(_base + offset); | |
466 int decodeInt16(int offset) => | |
467 _buffer.getInt16(_base + offset, Endianness.LITTLE_ENDIAN); | |
468 int decodeUint16(int offset) => | |
469 _buffer.getUint16(_base + offset, Endianness.LITTLE_ENDIAN); | |
470 int decodeInt32(int offset) => | |
471 _buffer.getInt32(_base + offset, Endianness.LITTLE_ENDIAN); | |
472 int decodeUint32(int offset) => | |
473 _buffer.getUint32(_base + offset, Endianness.LITTLE_ENDIAN); | |
474 int decodeInt64(int offset) => | |
475 _buffer.getInt64(_base + offset, Endianness.LITTLE_ENDIAN); | |
476 int decodeUint64(int offset) => | |
477 _buffer.getUint64(_base + offset,Endianness.LITTLE_ENDIAN); | |
478 double decodeFloat(int offset) => | |
479 _buffer.getFloat32(_base + offset, Endianness.LITTLE_ENDIAN); | |
480 double decodeDouble(int offset) => | |
481 _buffer.getFloat64(_base + offset, Endianness.LITTLE_ENDIAN); | |
482 | |
483 bool decodeBool(int offset, int bit) => | |
484 (decodeUint8(offset) & (1 << bit)) != 0; | |
485 | |
486 core.MojoHandle decodeHandle(int offset, bool nullable) { | |
487 int index = decodeInt32(offset); | |
488 if (index == -1) { | |
489 if (!nullable) { | |
490 throw 'Trying to decode an invalid handle from a non-nullable type.'; | |
491 } | |
492 return new core.MojoHandle(core.MojoHandle.INVALID); | |
493 } | |
494 return _handles[index]; | |
495 } | |
496 | |
497 core.MojoMessagePipeEndpoint decodeMessagePipeHandle( | |
498 int offset, bool nullable) => | |
499 new core.MojoMessagePipeEndpoint(decodeHandle(offset, nullable)); | |
500 | |
501 core.MojoDataPipeConsumer decodeConsumerHandle(int offset, bool nullable) => | |
502 new core.MojoDataPipeConsumer(decodeHandle(offset, nullable)); | |
503 | |
504 core.MojoDataPipeProducer decodeProducerHandle(int offset, bool nullable) => | |
505 new core.MojoDataPipeProducer(decodeHandle(offset, nullable)); | |
506 | |
507 core.MojoSharedBuffer decodeSharedBufferHandle(int offset, bool nullable) => | |
508 new core.MojoSharedBuffer(decodeHandle(offset, nullable)); | |
509 | |
510 Client decodeServiceInterface( | |
511 int offset, bool nullable, Function clientFactory) { | |
512 var endpoint = decodeMessagePipeHandle(offset, nullable); | |
513 return endpoint.handle.isValid ? clientFactory(endpoint) : null; | |
514 } | |
515 | |
516 Interface decodeInterfaceRequest( | |
517 int offset, bool nullable, Function interfaceFactory) { | |
518 var endpoint = decodeMessagePipeHandle(offset, nullable); | |
519 return endpoint.handle.isValid ? interfaceFactory(endpoint) : null; | |
520 } | |
521 | |
522 Decoder decodePointer(int offset, bool nullable) { | |
523 int basePosition = _base + offset; | |
524 int pointerOffset = decodeUint64(offset); | |
525 if (pointerOffset == 0) { | |
526 if (!nullable) { | |
527 throw 'Trying to decode a null pointer for a non-nullable type'; | |
528 } | |
529 return null; | |
530 } | |
531 int newPosition = (basePosition + pointerOffset); | |
532 return new Decoder.atOffset(this, newPosition); | |
533 } | |
534 | |
535 DataHeader decodeDataHeader() { | |
536 int size = decodeUint32(DataHeader.kSizeOffset); | |
537 int numFields = decodeUint32(DataHeader.kNumFieldsOffset); | |
538 return new DataHeader(size, numFields); | |
539 } | |
540 | |
541 // Decode arrays. | |
542 DataHeader decodeDataHeaderForBoolArray(int expectedLength) { | |
543 var header = decodeDataHeader(); | |
544 if (header.size < DataHeader.kHeaderSize + (header.numFields + 7) ~/ 8) { | |
545 throw 'Array header is incorrect'; | |
546 } | |
547 if ((expectedLength != kUnspecifiedArrayLength) && | |
548 (header.numFields != expectedLength)) { | |
549 throw 'Incorrect array length'; | |
550 } | |
551 return header; | |
552 } | |
553 | |
554 List<bool> decodeBoolArray(int offset, int nullability, int expectedLength) { | |
555 Decoder d = decodePointer(offset, isArrayNullable(nullability)); | |
556 if (d == null) { | |
557 return null; | |
558 } | |
559 var header = d.decodeDataHeaderForBoolArray(expectedLength); | |
560 var bytes = new Uint8List.view( | |
561 d._buffer.buffer, | |
562 d._buffer.offsetInBytes + d._base + DataHeader.kHeaderSize, | |
563 (header.numFields + 7) ~/ kAlignment); | |
564 var result = new List<bool>(header.numFields); | |
565 for (int i = 0; i < bytes.lengthInBytes; ++i) { | |
566 for (int j = 0; j < kAlignment; ++j) { | |
567 int boolIndex = i * kAlignment + j; | |
568 if (boolIndex < result.length) { | |
569 result[boolIndex] = (bytes[i] & (1 << j)) != 0; | |
570 } | |
571 } | |
572 } | |
573 return result; | |
574 } | |
575 | |
576 DataHeader decodeDataHeaderForArray(int elementSize, int expectedLength) { | |
577 var header = decodeDataHeader(); | |
578 if (header.size < DataHeader.kHeaderSize + header.numFields * elementSize) { | |
579 throw 'Array header is incorrect: $header, elementSize = $elementSize'; | |
580 } | |
581 if ((expectedLength != kUnspecifiedArrayLength) && | |
582 (header.numFields != expectedLength)) { | |
583 throw 'Incorrect array length.'; | |
584 } | |
585 return header; | |
586 } | |
587 | |
588 DataHeader decodeDataHeaderForPointerArray(int expectedLength) => | |
589 decodeDataHeaderForArray(kPointerSize, expectedLength); | |
590 | |
591 List<int> decodeArray(Function arrayViewer, | |
592 int elementSize, | |
593 int offset, | |
594 int nullability, | |
595 int expectedLength) { | |
596 Decoder d = decodePointer(offset, isArrayNullable(nullability)); | |
597 if (d == null) { | |
598 return null; | |
599 } | |
600 var header = d.decodeDataHeaderForArray(elementSize, expectedLength); | |
601 return arrayViewer( | |
602 d._buffer.buffer, | |
603 d._buffer.offsetInBytes + d._base + DataHeader.kHeaderSize, | |
604 header.numFields); | |
605 } | |
606 | |
607 List<int> decodeInt8Array( | |
608 int offset, int nullability, int expectedLength) => | |
609 decodeArray((b, s, l) => new Int8List.view(b, s, l), | |
610 1, offset, nullability, expectedLength); | |
611 | |
612 List<int> decodeUint8Array( | |
613 int offset, int nullability, int expectedLength) => | |
614 decodeArray((b, s, l) => new Uint8List.view(b, s, l), | |
615 1, offset, nullability, expectedLength); | |
616 | |
617 List<int> decodeInt16Array( | |
618 int offset, int nullability, int expectedLength) => | |
619 decodeArray((b, s, l) => new Int16List.view(b, s, l), | |
620 2, offset, nullability, expectedLength); | |
621 | |
622 List<int> decodeUint16Array( | |
623 int offset, int nullability, int expectedLength) => | |
624 decodeArray((b, s, l) => new Uint16List.view(b, s, l), | |
625 2, offset, nullability, expectedLength); | |
626 | |
627 List<int> decodeInt32Array( | |
628 int offset, int nullability, int expectedLength) => | |
629 decodeArray((b, s, l) => new Int32List.view(b, s, l), | |
630 4, offset, nullability, expectedLength); | |
631 | |
632 List<int> decodeUint32Array( | |
633 int offset, int nullability, int expectedLength) => | |
634 decodeArray((b, s, l) => new Uint32List.view(b, s, l), | |
635 4, offset, nullability, expectedLength); | |
636 | |
637 List<int> decodeInt64Array( | |
638 int offset, int nullability, int expectedLength) => | |
639 decodeArray((b, s, l) => new Int64List.view(b, s, l), | |
640 8, offset, nullability, expectedLength); | |
641 | |
642 List<int> decodeUint64Array( | |
643 int offset, int nullability, int expectedLength) => | |
644 decodeArray((b, s, l) => new Uint64List.view(b, s, l), | |
645 8, offset, nullability, expectedLength); | |
646 | |
647 List<double> decodeFloatArray( | |
648 int offset, int nullability, int expectedLength) => | |
649 decodeArray((b, s, l) => new Float32List.view(b, s, l), | |
650 4, offset, nullability, expectedLength); | |
651 | |
652 List<double> decodeDoubleArray( | |
653 int offset, int nullability, int expectedLength) => | |
654 decodeArray((b, s, l) => new Float64List.view(b, s, l), | |
655 8, offset, nullability, expectedLength); | |
656 | |
657 List _handleArrayDecodeHelper(Function elementDecoder, | |
658 int offset, | |
659 int nullability, | |
660 int expectedLength) { | |
661 Decoder d = decodePointer(offset, isArrayNullable(nullability)); | |
662 if (d == null) { | |
663 return null; | |
664 } | |
665 var header = d.decodeDataHeaderForArray(4, expectedLength); | |
666 var result = new List(header.numFields); | |
667 for (int i = 0; i < result.length; ++i) { | |
668 result[i] = elementDecoder( | |
669 d, | |
670 DataHeader.kHeaderSize + kSerializedHandleSize * i, | |
671 isElementNullable(nullability)); | |
672 } | |
673 return result; | |
674 | |
675 } | |
676 | |
677 List<core.MojoHandle> decodeHandleArray( | |
678 int offset, int nullability, int expectedLength) => | |
679 _handleArrayDecodeHelper((d, o, n) => d.decodeHandle(o, n), | |
680 offset, nullability, expectedLength); | |
681 | |
682 List<core.MojoDataPipeConsumer> decodeConsumerHandleArray( | |
683 int offset, int nullability, int expectedLength) => | |
684 _handleArrayDecodeHelper((d, o, n) => d.decodeConsumerHandle(o, n), | |
685 offset, nullability, expectedLength); | |
686 | |
687 List<core.MojoDataPipeProducer> decodeProducerHandleArray( | |
688 int offset, int nullability, int expectedLength) => | |
689 _handleArrayDecodeHelper((d, o, n) => d.decodeProducerHandle(o, n), | |
690 offset, nullability, expectedLength); | |
691 | |
692 List<core.MojoMessagePipeEndpoint> decodeMessagePipeHandleArray( | |
693 int offset, int nullability, int expectedLength) => | |
694 _handleArrayDecodeHelper((d, o, n) => d.decodeMessagePipeHandle(o, n), | |
695 offset, nullability, expectedLength); | |
696 | |
697 List<core.MojoSharedBuffer> decodeSharedBufferHandleArray( | |
698 int offset, int nullability, int expectedLength) => | |
699 _handleArrayDecodeHelper((d, o, n) => d.decodeSharedBufferHandle(o, n), | |
700 offset, nullability, expectedLength); | |
701 | |
702 List<Interface> decodeInterfaceRequestArray( | |
703 int offset, | |
704 int nullability, | |
705 int expectedLength, | |
706 Function interfaceFactory) => | |
707 _handleArrayDecodeHelper( | |
708 (d, o, n) => d.decodeInterfaceRequest(o, n, interfaceFactory), | |
709 offset, nullability, expectedLength); | |
710 | |
711 List<Client> decodeServiceInterfaceArray( | |
712 int offset, | |
713 int nullability, | |
714 int expectedLength, | |
715 Function clientFactory) => | |
716 _handleArrayDecodeHelper( | |
717 (d, o, n) => d.decodeServiceInterface(o, n, clientFactory), | |
718 offset, nullability, expectedLength); | |
719 | |
720 static String _stringOfUtf8(Uint8List bytes) => | |
721 (const Utf8Decoder()).convert(bytes.toList()); | |
722 | |
723 String decodeString(int offset, bool nullable) { | |
724 int nullability = nullable ? kArrayNullable : 0; | |
725 var bytes = decodeUint8Array(offset, nullability, kUnspecifiedArrayLength); | |
726 if (bytes == null) { | |
727 return null; | |
728 } | |
729 return _stringOfUtf8(bytes); | |
730 } | |
731 } | |
OLD | NEW |