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

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

Issue 674383002: Initial work on Dart bindings for Mojo. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Merge. Work on templates. Created 6 years, 1 month 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 part of bindings;
6
7 const int kAlignment = 8;
8 const int kArrayHeaderSize = 8;
9 const int kStructHeaderSize = 8;
10 const int kMessageHeaderSize = 16;
11 const int kMessageWithRequestIDHeaderSize = 24;
12 const int kMapStructPayloadSize = 16;
13 const int kStructHeaderNumBytesOffset = 0;
14 const int kStructHeaderNumFieldsOffset = 4;
15 const int kEncodedInvalidHandleValue = 0xffffffff;
16
17
18 int align(int size) => size + (kAlignment - (size % kAlignment)) % kAlignment;
19 bool isAligned(offset) => (offset >= 0) && ((offset % kAlignment) == 0);
20
21
22 Uint8List utf8OfString(String s) =>
23 (new Uint8List.fromList((const Utf8Encoder()).convert(s)));
24
25
26 String stringOfUtf8(Uint8List bytes) =>
27 (const Utf8Decoder()).convert(bytes.toList());
28
29
30 Object _callDecode(Object typ_or_inst, MojoDecoder decoder) {
31 if (typ_or_inst is Type) {
32 return reflectClass(typ_or_inst).invoke(#decode, [decoder]).reflectee;
33 } else {
34 return typ_or_inst.decode(decoder);
35 }
36 }
37
38
39 void _callEncode(Object typ_or_inst, MojoEncoder encoder, Object val) {
40 if (typ_or_inst is Type) {
41 reflectClass(typ_or_inst).invoke(#encode, [encoder, val]);
42 } else {
43 typ_or_inst.encode(encoder, val);
44 }
45 }
46
47
48 int getEncodedSize(Object typ_or_inst) {
49 if (typ_or_inst is Type) {
50 return reflectClass(typ_or_inst).getField(#encodedSize).reflectee;
51 } else {
52 return typ_or_inst.encodedSize;
53 }
54 }
55
56
57 class MojoDecoder {
58 ByteData buffer;
59 List<int> handles;
60 int base;
61 int next;
62
63 MojoDecoder(this.buffer, this.handles, this.base) {
64 next = base;
65 }
66
67 void skip(int offset) {
68 next += offset;
69 }
70
71 int readInt8() {
72 int result = buffer.getInt8(next);
73 next += 1;
74 return result;
75 }
76
77 int readUint8() {
78 int result = buffer.getUint8(next);
79 next += 1;
80 return result;
81 }
82
83 int readInt16() {
84 int result = buffer.getInt16(next, Endianness.HOST_ENDIAN);
85 next += 2;
86 return result;
87 }
88
89 int readUint16() {
90 int result = buffer.getUint16(next, Endianness.HOST_ENDIAN);
91 next += 2;
92 return result;
93 }
94
95 int readInt32() {
96 int result = buffer.getInt32(next, Endianness.HOST_ENDIAN);
97 next += 4;
98 return result;
99 }
100
101 int readUint32() {
102 int result = buffer.getUint32(next, Endianness.HOST_ENDIAN);
103 next += 4;
104 return result;
105 }
106
107 int readInt64() {
108 int result = buffer.getInt64(next, Endianness.HOST_ENDIAN);
109 next += 8;
110 return result;
111 }
112
113 int readUint64() {
114 int result = buffer.getUint64(next, Endianness.HOST_ENDIAN);
115 next += 8;
116 return result;
117 }
118
119 double readFloat() {
120 double result = buffer.getFloat32(next,Endianness.HOST_ENDIAN);
121 next += 4;
122 return result;
123 }
124
125 double readDouble() {
126 double result = buffer.getFloat64(next, Endianness.HOST_ENDIAN);
127 next += 8;
128 return result;
129 }
130
131 int decodePointer() {
132 int offsetPointer = next;
133 int offset = readUint64();
134 if (offset == 0) {
135 return 0;
136 }
137 return offsetPointer + offset;
138 }
139
140 MojoDecoder decodeAndCreateDecoder(int offset) {
141 return new MojoDecoder(buffer, handles, offset);
142 }
143
144 int decodeHandle() {
145 return handles[readUint32()];
146 }
147
148 String decodeString() {
149 int num_bytes = readUint32();
150 int num_elements = readUint32();
151 int base = next;
152 next += num_elements;
153 return stringOfUtf8(buffer.buffer.asUint8List(base, num_elements));
154 }
155
156 List decodeArray(Object t) {
157 int num_bytes = readUint32();
158 int num_elements = readUint32();
159 if (t == PackedBool) {
160 int b;
161 List<bool> result = new List<bool>(num_elements);
162 for (int i = 0; i < num_elements; i++) {
163 if ((i % 8) == 0) {
164 b = readUint8();
165 }
166 result[i] = ((b & (1 << (i % 8)) != 0) ? true : false);
167 }
168 return result;
169 } else {
170 List result = new List(num_elements);
171 for (int i = 0; i < num_elements; i++) {
172 result[i] = _callDecode(t, this);
173 }
174 return result;
175 }
176 }
177
178 Object decodeStruct(Object t) {
179 return _callDecode(t, this);
180 }
181
182 Object decodeStructPointer(Object t) {
183 int pointer = decodePointer();
184 if (pointer == 0) {
185 return null;
186 }
187 return _callDecode(t, decodeAndCreateDecoder(pointer));
188 }
189
190 List decodeArrayPointer(Object t) {
191 int pointer = decodePointer();
192 if (pointer == 0) {
193 return null;
194 }
195 return decodeAndCreateDecoder(pointer).decodeArray(t);
196 }
197
198 String decodeStringPointer() {
199 int pointer = decodePointer();
200 if (pointer == 0) {
201 return null;
202 }
203 return decodeAndCreateDecoder(pointer).decodeString();
204 }
205
206 Map decodeMap(Object keyType, Object valType) {
207 skip(4); // number of bytes.
208 skip(4); // number of fields.
209 List keys = decodeArrayPointer(keyType);
210 List values = decodeArrayPointer(valType);
211 return new Map.fromIterables(keyes, values);
212 }
213
214 Map decodeMapPointer(Object keyType, Object valType) {
215 int pointer = this.decodePointer();
216 if (pointer == 0) {
217 return null;
218 }
219 MojoDecoder decoder = decodeAndCreateDecoder(pointer);
220 return decoder.decodeMap(keyType, valType);
221 }
222 }
223
224
225 class MojoEncoder {
226 ByteData buffer;
227 List handles;
228 int base;
229 int next;
230 int extent;
231
232 MojoEncoder(this.buffer, this.handles, this.base, this.extent) {
233 next = base;
234 }
235
236 void skip(int offset) {
237 next += offset;
238 }
239
240 void writeInt8(int val) {
241 buffer.setInt8(next, val);
242 next += 1;
243 }
244
245 void writeUint8(int val) {
246 buffer.setUint8(next, val);
247 next += 1;
248 }
249
250 void writeInt16(int val) {
251 buffer.setInt16(next, val, Endianness.HOST_ENDIAN);
252 next += 2;
253 }
254
255 void writeUint16(int val) {
256 buffer.setUint16(next, val, Endianness.HOST_ENDIAN);
257 next += 2;
258 }
259
260 void writeInt32(int val) {
261 buffer.setInt32(next, val, Endianness.HOST_ENDIAN);
262 next += 4;
263 }
264
265 void writeUint32(int val) {
266 buffer.setUint32(next, val, Endianness.HOST_ENDIAN);
267 next += 4;
268 }
269
270 void writeInt64(int val) {
271 buffer.setInt64(next, val, Endianness.HOST_ENDIAN);
272 next += 8;
273 }
274
275 void writeUint64(int val) {
276 buffer.setUint64(next, val, Endianness.HOST_ENDIAN);
277 next += 8;
278 }
279
280 void writeFloat(double val) {
281 buffer.setFloat32(next, val, Endianness.HOST_ENDIAN);
282 next += 4;
283 }
284
285 void writeDouble(double val) {
286 buffer.setFloat64(next, val, Endianness.HOST_ENDIAN);
287 next += 8;
288 }
289
290 void encodePointer(int pointer) {
291 if (pointer == null) {
292 writeUint64(0);
293 return;
294 }
295 int offset = pointer - next;
296 writeUint64(offset);
297 }
298
299 void grow(int new_size) {
300 Uint8List new_buffer = new Uint8List(new_size);
301 new_buffer.setRange(0, next, buffer.buffer.asUint8List());
302 buffer = new_buffer.buffer.asByteData();
303 }
304
305 int alloc(int size_request) {
306 int pointer = extent;
307 extent += size_request;
308 if (extent > buffer.lengthInBytes) {
309 int new_size = buffer.lengthInBytes + size_request;
310 new_size += new_size ~/ 2;
311 grow(new_size);
312 }
313 return pointer;
314 }
315
316 MojoEncoder createAndEncodeEncoder(int size) {
317 int pointer = alloc(align(size));
318 encodePointer(pointer);
319 return new MojoEncoder(buffer, handles, pointer, extent);
320 }
321
322 void encodeHandle(int handle) {
323 handles.add(handle);
324 writeUint32(handles.length - 1);
325 }
326
327 void encodeString(String val) {
328 Uint8List utf8string = utf8OfString(val);
329 int num_elements = utf8string.lengthInBytes;
330 int num_bytes = kArrayHeaderSize + num_elements;
331 writeUint32(num_bytes);
332 writeUint32(num_elements);
333 buffer.buffer.asUint8List().setRange(next, next + num_elements, utf8string);
334 next += num_elements;
335 }
336
337 void encodeArray(Object t, List val, [int num_elements, int encoded_size]) {
338 if (num_elements == null) {
339 num_elements = val.length;
340 }
341 if (encoded_size == null) {
342 encoded_size = kArrayHeaderSize + (getEncodedSize(t) * num_elements);
343 }
344
345 writeUint32(encoded_size);
346 writeUint32(num_elements);
347
348 if (t == PackedBool) {
349 int b = 0;
350 for (int i = 0; i < num_elements; i++) {
351 if (val[i]) {
352 b |= (1 << (i % 8));
353 }
354 if (((i % 8) == 7) || (i == (num_elements - 1))) {
355 Uint8.encode(this, b);
356 }
357 }
358 } else {
359 for (int i = 0; i < num_elements; i++) {
360 _callEncode(t, this, val[i]);
361 }
362 }
363 }
364
365 void encodeStruct(Object t, Object val) {
366 _callEncode(t, this, val);
367 }
368
369 void encodeStructPointer(Object t, Object val) {
370 if (val == null) {
371 encodePointer(val);
372 return;
373 }
374 MojoEncoder encoder = createAndEncodeEncoder(getEncodedSize(t));
375 _callEncode(t, encoder, val);
376 extent = encoder.extent;
377 buffer = encoder.buffer;
378 }
379
380 void encodeArrayPointer(Object t, List val) {
381 if (val == null) {
382 encodePointer(val);
383 return;
384 }
385 int num_elements = val.length;
386 int encoded_size = kArrayHeaderSize + ((t == PackedBool) ?
387 (num_elements / 8).ceil() : (getEncodedSize(t) * num_elements));
388 MojoEncoder encoder = createAndEncodeEncoder(encoded_size);
389 encoder.encodeArray(t, val, num_elements, encoded_size);
390 extent = encoder.extent;
391 buffer = encoder.buffer;
392 }
393
394 void encodeStringPointer(String val) {
395 if (val == null) {
396 encodePointer(val);
397 return;
398 }
399 int encoded_size = kArrayHeaderSize + utf8OfString(val).lengthInBytes;
400 MojoEncoder encoder = createAndEncodeEncoder(encoded_size);
401 encoder.encodeString(val);
402 extent = encoder.extent;
403 buffer = encoder.buffer;
404 }
405
406 void encodeMap(Object keyType, Object valType, Map val) {
407 List keys = val.keys;
408 List vals = val.values;
409 writeUint32(kStructHeaderSize + kMapStructPayloadSize);
410 writeUint32(2);
411 encodeArrayPointer(keyType, keys);
412 encodeArrayPointer(valType, vals);
413 }
414
415 void encodeMapPointer(Object keyTYpe, Object valType, Map val) {
416 if (val == null) {
417 encodePointer(val);
418 return;
419 }
420 int encoded_size = kStructHeaderSize + kMapStructPayloadSize;
421 MojoEncoder encoder = createAndEncodeEncoder(encoded_size);
422 encoder.encodeMap(keyType, valType, val);
423 extent = encoder.extent;
424 buffer = encoder.buffer;
425 }
426 }
427
428
429 const int kMessageNameOffset = kStructHeaderSize;
430 const int kMessageFlagsOffset = kMessageNameOffset + 4;
431 const int kMessageRequestIDOffset = kMessageFlagsOffset + 4;
432 const int kMessageExpectsResponse = 1 << 0;
433 const int kMessageIsResponse = 1 << 1;
434
435 class Message {
436 ByteData buffer;
437 List<int> handles;
438
439 Message(this.buffer, this.handles);
440
441 int getHeaderNumBytes() => buffer.getUint32(kStructHeaderNumBytesOffset);
442 int getHeaderNumFields() => buffer.getUint32(kStructHeaderNumFieldsOffset);
443 int getName() => buffer.getUint32(kMessageNameOffset);
444 int getFlags() => buffer.getUint32(kMessageFlagsOffset);
445 bool isResponse() => (getFlags() & kMessageIsResponse) != 0;
446 bool expectsResponse() => (getFlags() & kMessageExpectsResponse) != 0;
447
448 void setRequestID(int id) {
449 buffer.setUint64(kMessageRequestIDOffset, id);
450 }
451 }
452
453
454 class MessageBuilder {
455 ByteData buffer;
456 List<int> handles;
457 int base;
458
459 MessageBuilder(int name, int payload_size) {
460 int num_bytes = kMessageHeaderSize + payload_size;
461 buffer = new ByteData(num_bytes);
462 handles = [];
463 base = 0;
464 MojoEncoder encoder = createEncoder(kMessageHeaderSize);
465 encoder.writeUint32(kMessageHeaderSize);
466 encoder.writeUint32(2); // num_fields;
467 encoder.writeUint32(name);
468 encoder.writeUint32(0); // flags.
469 base = encoder.next;
470 buffer = encoder.buffer;
471 }
472
473 MojoEncoder createEncoder(int size) {
474 return new MojoEncoder(buffer, handles, base, base + size);
475 }
476
477 void encodeStruct(Object t, Object val) {
478 MojoEncoder encoder = createEncoder(getEncodedSize(t));
479 _callEncode(t, encoder, val);
480 base = encoder.next;
481 buffer = encoder.buffer;
482 }
483
484 Message finish() {
485 // trip buffer down to base.
486 Message message = new Message(buffer, handles);
487 buffer = null;
488 handles = null;
489 return message;
490 }
491 }
492
493
494 class MessageWithRequestIDBuilder extends MessageBuilder {
495 MessageWithRequestIDBuilder(
496 int name, int payload_size, int flags, int requestID) {
497 int num_bytes = kMessageWithRequestIDHeaderSize + payload_size;
498 buffer = new ByteData(num_bytes);
499 handles = [];
500 base = 0;
501
502 MojoEncoder encoder = createEncoder(0, kMessageWithRequestIDHeaderSize);
503 encoder.writeUint32(kMessageWithRequestIDHeaderSize);
504 encoder.writeUint32(3); // num_fields.
505 encoder.writeUint32(name);
506 encoder.writeUint32(flags);
507 encoder.writeUint64(requestID);
508 base = encoder.next;
509 buffer = encoder.buffer;
510 }
511 }
512
513
514 class MessageReader {
515 MojoDecoder decoder;
516 int payload_size;
517 int name;
518 int flags;
519 int requestID;
520
521 MessageReader(Message message) {
522 decoder = new MojoDecoder(message.buffer, message.handles, 0);
523
524 int message_header_size = decoder.readUint32();
525 payload_size = message.buffer.lengthInBytes - message_header_size;
526
527 int num_fields = decoder.readUint32();
528 name = decoder.readUint32();
529 flags = decoder.readUint32();
530
531 if (num_fields >= 3) {
532 requestID = decoder.readUint64();
533 }
534 decoder.skip(message_header_size - decoder.next);
535 }
536
537 Object decodeStruct(Object t) => _callDecode(t, decoder);
538 }
539
540
541 abstract class MojoType<T> {
542 static const int encodedSize = 0;
543 static T decode(MojoDecoder decoder) { return null }
544 static void encode(MojoEncoder encoder, T val) {}
545 }
546
547
548 // I guess we'll do this like JavaScript...
549 class PackedBool {}
550
551 class Int8 implements MojoType<int> {
552 static const int encodedSize = 1;
553 static int decode(MojoDecoder decoder) => decoder.readInt8();
554 static void encode(MojoEncoder encoder, int val) {
555 encoder.writeInt8(val);
556 }
557 }
558
559
560 class Uint8 implements MojoType<int> {
561 static const int encodedSize = 1;
562 static int decode(MojoDecoder decoder) => decoder.readUint8();
563 static void encode(MojoEncoder encoder, int val) {
564 encoder.writeUint8(val);
565 }
566 }
567
568
569 class Int16 implements MojoType<int> {
570 static const int encodedSize = 2;
571 static int decode(MojoDecoder decoder) => decoder.readInt16();
572 static void encode(MojoEncoder encoder, int val) {
573 encoder.writeInt16(val);
574 }
575 }
576
577
578 class Uint16 implements MojoType<int> {
579 static const int encodedSize = 2;
580 static int decode(MojoDecoder decoder) => decoder.readUint16();
581 static void encode(MojoEncoder encoder, int val) {
582 encoder.writeUint16(val);
583 }
584 }
585
586
587 class Int32 implements MojoType<int> {
588 static const int encodedSize = 4;
589 static int decode(MojoDecoder decoder) => decoder.readInt32();
590 static void encode(MojoEncoder encoder, int val) {
591 encoder.writeInt32(val);
592 }
593 }
594
595
596 class Uint32 implements MojoType<int> {
597 static const int encodedSize = 4;
598 static int decode(MojoDecoder decoder) => decoder.readUint32();
599 static void encode(MojoEncoder encoder, int val) {
600 encoder.writeUint32(val);
601 }
602 }
603
604
605 class Int64 implements MojoType<int> {
606 static const int encodedSize = 8;
607 static int decode(MojoDecoder decoder) => decoder.readInt64();
608 static void encode(MojoEncoder encoder, int val) {
609 encoder.writeInt64(val);
610 }
611 }
612
613
614 class Uint64 implements MojoType<int> {
615 static const int encodedSize = 8;
616 static int decode(MojoDecoder decoder) => decoder.readUint64();
617 static void encode(MojoEncoder encoder, int val) {
618 encoder.writeUint64(val);
619 }
620 }
621
622
623 class MojoString implements MojoType<String> {
624 static const int encodedSize = 8;
625 static String decode(MojoDecoder decoder) => decoder.decodeStringPointer();
626 static void encode(MojoEncoder encoder, String val) {
627 encoder.encodeStringPointer(val);
628 }
629 }
630
631
632 class NullableMojoString implements MojoType<String> {
633 static const int encodedSize = MojoString.encodedSize;
634 static var decode = MojoString.decode;
635 static var encode = MojoString.encode;
636 }
637
638
639 class Float implements MojoType<double> {
640 static const int encodedSize = 4;
641 static double decode(MojoDecoder decoder) => decoder.readFloat();
642 static void encode(MojoEncoder encoder, double val) {
643 encoder.writeFloat(val);
644 }
645 }
646
647
648 class Double implements MojoType<double> {
649 static const int encodedSize = 8;
650 static double decode(MojoDecoder decoder) => decoder.readDouble();
651 static void encode(MojoEncoder encoder, double val) {
652 encoder.writeDouble(val);
653 }
654 }
655
656
657 class PointerTo {
658 Object t;
659
660 PointerTo(this.t);
661
662 int encodedSize = 8;
663 Object decode(MojoDecoder decoder) {
664 int pointer = decoder.decodePointer();
665 if (pointer == 0) {
666 return null;
667 }
668 return _callDecode(t, decoder.decodeAndCreateDecoder(pointer));
669 }
670 void encode(MojoEncoder encoder, Object val) {
671 if (val == null) {
672 encoder.encodePointer(val);
673 return;
674 }
675 MojoEncoder obj_encoder = encoder.createAndEncodeEncoder(getEncodedSize(t));
676 _callEncode(t, obj_encoder, val);
677 }
678 }
679
680
681 class NullablePointerTo extends PointerTo {
682 static const int encodedSize = 8;
683 }
684
685
686 class ArrayOf {
687 Object t;
688 int length;
689
690 ArrayOf(Object t, [int length = 0]) : t = t, length = length;
691
692 int dimensions() => [length].addAll((t is ArrayOf) ? t.dimensions() : []);
693
694 int encodedSize = 8;
695 List decode(MojoDecoder decoder) => decoder.decodeArrayPointer(t);
696 void encode(MojoEncoder encoder, List val) {
697 encoder.encodeArrayPointer(t, val);
698 }
699 }
700
701
702 class NullableArrayOf extends ArrayOf {
703 static const int encodedSize = ArrayOf.encodedSize;
704 }
705
706
707 class Handle implements MojoType<int> {
708 static const int encodedSize = 4;
709 static int decode(MojoDecoder decoder) => decoder.decodeHandle();
710 static void encode(MojoEncoder encoder, int val) {
711 encoder.encodeHandle(val);
712 }
713 }
714
715
716 class NullableHandle implements MojoType<int> {
717 static const int encodedSize = Handle.encodedSize;
718 static const decode = Handle.decode;
719 static const encode = Handle.encode;
720 }
OLDNEW
« no previous file with comments | « mojo/public/dart/bindings/lib/src/client.dart ('k') | mojo/public/dart/bindings/lib/src/interface.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698