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

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

Issue 830593003: Update mojo sdk to rev 9fbbc4f0fef1187312316c0ed992342474e139f1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cherry-pick mojo 9d3b8dd17f12d20035a14737fdc38dd926890ff8 Created 5 years, 11 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/client.dart ('k') | mojo/public/dart/src/data_pipe.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // TODO(zra): Rewrite MojoDecoder and MojoEncoder using Dart idioms, and make
6 // corresponding changes to the bindings generation script.
7
8 part of bindings; 5 part of bindings;
9 6
7 int align(int size) => size + (kAlignment - (size % kAlignment)) % kAlignment;
8
10 const int kAlignment = 8; 9 const int kAlignment = 8;
11 const int kArrayHeaderSize = 8; 10 const int kSerializedHandleSize = 4;
12 const int kStructHeaderSize = 8; 11 const int kPointerSize = 8;
13 const int kMessageHeaderSize = 16; 12 const DataHeader kMapStructHeader = const DataHeader(24, 2);
14 const int kMessageWithRequestIDHeaderSize = 24; 13 const int kUnspecifiedArrayLength = -1;
15 const int kMapStructPayloadSize = 16; 14 const int kNothingNullable = 0;
16 const int kStructHeaderNumBytesOffset = 0; 15 const int kArrayNullable = (1 << 0);
17 const int kStructHeaderNumFieldsOffset = 4; 16 const int kElementNullable = (1 << 1);
18 const int kEncodedInvalidHandleValue = 0xffffffff; 17
19 const String kErrorUnsigned = "Passing negative value to unsigned encoder"; 18 bool isArrayNullable(int nullability) => (nullability & kArrayNullable) > 0;
20 19 bool isElementNullable(int nullability) => (nullability & kElementNullable) > 0;
21 20
22 int align(int size) => size + (kAlignment - (size % kAlignment)) % kAlignment; 21 class _EncoderBuffer {
23 bool isAligned(offset) => (offset >= 0) && ((offset % kAlignment) == 0); 22 ByteData buffer;
24 23 List<core.MojoHandle> handles;
25 24 int extent;
26 Uint8List utf8OfString(String s) => 25
27 (new Uint8List.fromList((const Utf8Encoder()).convert(s))); 26 static const int kInitialBufferSize = 1024;
28 27
29 28 _EncoderBuffer([int size = -1]) :
30 String stringOfUtf8(Uint8List bytes) => 29 buffer = new ByteData(size > 0 ? size : kInitialBufferSize),
31 (const Utf8Decoder()).convert(bytes.toList()); 30 handles = [],
32 31 extent = 0;
33 32
34 // Given an argument that is either a Type or an instance: 33 void _grow(int newSize) {
35 // Invoke the static method "decode" of the Type, or the instance method 34 Uint8List newBuffer = new Uint8List(newSize);
36 // "decode" of the instance, on the MojoDecoder. 35 newBuffer.setRange(0, buffer.lengthInBytes, buffer.buffer.asUint8List());
37 Object _callDecode(Object typeOrInstance, MojoDecoder decoder) { 36 buffer = newBuffer.buffer.asByteData();
38 if (typeOrInstance is Type) { 37 }
39 return reflectClass(typeOrInstance).invoke(#decode, [decoder]).reflectee; 38
40 } else { 39 void claimMemory(int claimSize) {
41 return typeOrInstance.decode(decoder); 40 extent += claimSize;
42 } 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);
43 } 49 }
44 50
45 51 class Encoder {
46 // Given an argument that is either a Type or an instance: 52 _EncoderBuffer _buffer;
47 // Invoke the static method "encode" of the Type, or the instance method 53 int _base;
48 // "encode" of the instance, on the MojoEncoder and value to be encoded. 54
49 void _callEncode(Object typeOrInstance, MojoEncoder encoder, Object val) { 55 Encoder([int size = -1]) : _buffer = new _EncoderBuffer(size), _base = 0;
50 if (typeOrInstance is Type) { 56
51 reflectClass(typeOrInstance).invoke(#encode, [encoder, val]); 57 Encoder._fromBuffer(_EncoderBuffer buffer) :
52 } else { 58 _buffer = buffer,
53 typeOrInstance.encode(encoder, val); 59 _base = buffer.extent;
54 } 60
55 } 61 Encoder getEncoderAtOffset(DataHeader dataHeader) {
56 62 var result = new Encoder._fromBuffer(_buffer);
57 63 result.encodeDataHeader(dataHeader);
58 // Given an argument that is either a Type or an instance:
59 // Invoke the static getter "encodedSize" of the Type, or the instance getter
60 // "encodedSize" of the instance, and return the result.
61 int getEncodedSize(Object typeOrInstance) {
62 if (typeOrInstance is Type) {
63 return reflectClass(typeOrInstance).getField(#encodedSize).reflectee;
64 } else {
65 return typeOrInstance.encodedSize;
66 }
67 }
68
69
70 class MojoDecoder {
71 ByteData buffer;
72 List<core.RawMojoHandle> handles;
73 int base;
74 int next;
75
76 MojoDecoder(this.buffer, this.handles, this.base) {
77 next = base;
78 }
79
80 void skip(int offset) {
81 next += offset;
82 }
83
84 int readInt8() {
85 int result = buffer.getInt8(next);
86 next += 1;
87 return result; 64 return result;
88 } 65 }
89 66
90 int readUint8() { 67 Message get message => new Message(_buffer.trimmed, _buffer.handles);
91 int result = buffer.getUint8(next); 68
92 next += 1; 69 void encodeDataHeader(DataHeader dataHeader) {
93 return result; 70 _buffer.claimMemory(align(dataHeader.size));
94 } 71 encodeUint32(dataHeader.size, DataHeader.kSizeOffset);
95 72 encodeUint32(dataHeader.numFields, DataHeader.kNumFieldsOffset);
96 int readInt16() { 73 }
97 int result = buffer.getInt16(next, Endianness.LITTLE_ENDIAN); 74
98 next += 2; 75 static const String kErrorUnsigned =
99 return result; 76 'Passing negative value to unsigned encoder';
100 } 77
101 78 void encodeBool(bool value, int offset, int bit) {
102 int readUint16() { 79 if (value) {
103 int result = buffer.getUint16(next, Endianness.LITTLE_ENDIAN); 80 int encodedValue = _buffer.buffer.getUint8(_base + offset);
104 next += 2; 81 encodedValue |= (1 << bit);
105 return result; 82 _buffer.buffer.setUint8(_base + offset, encodedValue);
106 } 83 }
107 84 }
108 int readInt32() { 85
109 int result = buffer.getInt32(next, Endianness.LITTLE_ENDIAN); 86 void encodeInt8(int value, int offset) =>
110 next += 4; 87 _buffer.buffer.setInt8(_base + offset, value);
111 return result; 88
112 } 89 void encodeUint8(int value, int offset) {
113 90 if (value < 0) {
114 int readUint32() { 91 throw '$kErrorUnsigned: $val';
115 int result = buffer.getUint32(next, Endianness.LITTLE_ENDIAN); 92 }
116 next += 4; 93 _buffer.buffer.setUint8(_base + offset, value);
117 return result; 94 }
118 } 95
119 96 void encodeInt16(int value, int offset) =>
120 int readInt64() { 97 _buffer.buffer.setInt16(_base + offset, value, Endianness.LITTLE_ENDIAN);
121 int result = buffer.getInt64(next, Endianness.LITTLE_ENDIAN); 98
122 next += 8; 99 void encodeUint16(int value, int offset) {
123 return result; 100 if (value < 0) {
124 } 101 throw '$kErrorUnsigned: $val';
125 102 }
126 int readUint64() { 103 _buffer.buffer.setUint16(_base + offset, value, Endianness.LITTLE_ENDIAN);
127 int result = buffer.getUint64(next, Endianness.LITTLE_ENDIAN); 104 }
128 next += 8; 105
129 return result; 106 void encodeInt32(int value, int offset) =>
130 } 107 _buffer.buffer.setInt32(_base + offset, value, Endianness.LITTLE_ENDIAN);
131 108
132 double readFloat() { 109 void encodeUint32(int value, int offset) {
133 double result = buffer.getFloat32(next,Endianness.LITTLE_ENDIAN); 110 if (value < 0) {
134 next += 4; 111 throw '$kErrorUnsigned: $val';
135 return result; 112 }
136 } 113 _buffer.buffer.setUint32(_base + offset, value, Endianness.LITTLE_ENDIAN);
137 114 }
138 double readDouble() { 115
139 double result = buffer.getFloat64(next, Endianness.LITTLE_ENDIAN); 116 void encodeInt64(int value, int offset) =>
140 next += 8; 117 _buffer.buffer.setInt64(_base + offset, value, Endianness.LITTLE_ENDIAN);
141 return result; 118
142 } 119 void encodeUint64(int value, int offset) {
143 120 if (value < 0) {
144 int decodePointer() { 121 throw '$kErrorUnsigned: $val';
145 int offsetPointer = next; 122 }
146 int offset = readUint64(); 123 _buffer.buffer.setUint64(_base + offset, value, Endianness.LITTLE_ENDIAN);
147 if (offset == 0) { 124 }
148 return 0; 125
149 } 126 void encodeFloat(double value, int offset) =>
150 return offsetPointer + offset; 127 _buffer.buffer.setFloat32(_base + offset, value, Endianness.LITTLE_ENDIAN);
151 } 128
152 129 void encodeDouble(double value, int offset) =>
153 MojoDecoder decodeAndCreateDecoder(int offset) { 130 _buffer.buffer.setFloat64(_base + offset, value, Endianness.LITTLE_ENDIAN);
154 return new MojoDecoder(buffer, handles, offset); 131
155 } 132 void encodeHandle(core.MojoHandle value, int offset, bool nullable) {
156 133 if ((value == null) || !value.isValid) {
157 core.RawMojoHandle decodeHandle() { 134 encodeInvalideHandle(offset, nullable);
158 int handleIndex = readUint32();
159 return (handleIndex == kEncodedInvalidHandleValue) ?
160 new core.RawMojoHandle(core.RawMojoHandle.INVALID) :
161 handles[handleIndex];
162 }
163
164 String decodeString() {
165 int numBytes = readUint32();
166 int numElements = readUint32();
167 int base = next;
168 next += numElements;
169 return stringOfUtf8(buffer.buffer.asUint8List(base, numElements));
170 }
171
172 List decodeArray(Object type) {
173 int numBytes = readUint32();
174 int numElements = readUint32();
175 if (type == PackedBool) {
176 int b;
177 List<bool> result = new List<bool>(numElements);
178 for (int i = 0; i < numElements; i++) {
179 if ((i % 8) == 0) {
180 b = readUint8();
181 }
182 result[i] = ((b & (1 << (i % 8)) != 0) ? true : false);
183 }
184 return result;
185 } else { 135 } else {
186 List result = new List(numElements); 136 encodeUint32(_buffer.handles.length, offset);
187 for (int i = 0; i < numElements; i++) { 137 _buffer.handles.add(value);
188 result[i] = _callDecode(type, this); 138 }
189 } 139 }
190 return result; 140
191 } 141 void encodeNullPointer(int offset, bool nullable) {
192 } 142 if (!nullable) {
193 143 throw 'Trying to encode a null pointer for a non-nullable type';
194 Object decodeStruct(Object t) { 144 }
195 return _callDecode(t, this); 145 _buffer.buffer.setUint64(_base + offset, 0, Endianness.LITTLE_ENDIAN);
196 } 146 }
197 147
198 Object decodeStructPointer(Object t) { 148 void encodeInvalideHandle(int offset, bool nullable) {
199 int pointer = decodePointer(); 149 if (!nullable) {
200 if (pointer == 0) { 150 throw 'Trying to encode a null pointer for a non-nullable type';
201 return null; 151 }
202 } 152 _buffer.buffer.setInt32(_base + offset, -1, Endianness.LITTLE_ENDIAN);
203 return _callDecode(t, decodeAndCreateDecoder(pointer)); 153 }
204 } 154
205 155 void encodePointerToNextUnclaimed(int offset) =>
206 List decodeArrayPointer(Object type) { 156 encodeUint64(_buffer.extent - (_base + offset), offset);
207 int pointer = decodePointer(); 157
208 if (pointer == 0) { 158 void encodeStruct(Struct value, int offset, bool nullable) {
209 return null; 159 if (value == null) {
210 } 160 encodeNullPointer(offset, nullable);
211 return decodeAndCreateDecoder(pointer).decodeArray(type);
212 }
213
214 String decodeStringPointer() {
215 int pointer = decodePointer();
216 if (pointer == 0) {
217 return null;
218 }
219 return decodeAndCreateDecoder(pointer).decodeString();
220 }
221
222 Map decodeMap(Object keyType, Object valType) {
223 skip(4); // number of bytes.
224 skip(4); // number of fields.
225 List keys = decodeArrayPointer(keyType);
226 List values = decodeArrayPointer(valType);
227 return new Map.fromIterables(keys, values);
228 }
229
230 Map decodeMapPointer(Object keyType, Object valType) {
231 int pointer = this.decodePointer();
232 if (pointer == 0) {
233 return null;
234 }
235 MojoDecoder decoder = decodeAndCreateDecoder(pointer);
236 return decoder.decodeMap(keyType, valType);
237 }
238 }
239
240
241 class MojoEncoder {
242 ByteData buffer;
243 List<core.RawMojoHandle> handles;
244 int base;
245 int next;
246 int extent;
247
248 MojoEncoder(this.buffer, this.handles, this.base, this.extent) {
249 next = base;
250 }
251
252 void skip(int offset) {
253 next += offset;
254 }
255
256 void writeInt8(int val) {
257 buffer.setInt8(next, val);
258 next += 1;
259 }
260
261 void writeUint8(int val) {
262 if (val < 0) {
263 throw new ArgumentError("$kErrorUnsigned: $val");
264 }
265 buffer.setUint8(next, val);
266 next += 1;
267 }
268
269 void writeInt16(int val) {
270 buffer.setInt16(next, val, Endianness.LITTLE_ENDIAN);
271 next += 2;
272 }
273
274 void writeUint16(int val) {
275 if (val < 0) {
276 throw new ArgumentError("$kErrorUnsigned: $val");
277 }
278 buffer.setUint16(next, val, Endianness.LITTLE_ENDIAN);
279 next += 2;
280 }
281
282 void writeInt32(int val) {
283 buffer.setInt32(next, val, Endianness.LITTLE_ENDIAN);
284 next += 4;
285 }
286
287 void writeUint32(int val) {
288 if (val < 0) {
289 throw new ArgumentError("$kErrorUnsigned: $val");
290 }
291 buffer.setUint32(next, val, Endianness.LITTLE_ENDIAN);
292 next += 4;
293 }
294
295 void writeInt64(int val) {
296 buffer.setInt64(next, val, Endianness.LITTLE_ENDIAN);
297 next += 8;
298 }
299
300 void writeUint64(int val) {
301 if (val < 0) {
302 throw new ArgumentError("$kErrorUnsigned: $val");
303 }
304 buffer.setUint64(next, val, Endianness.LITTLE_ENDIAN);
305 next += 8;
306 }
307
308 void writeFloat(double val) {
309 buffer.setFloat32(next, val, Endianness.LITTLE_ENDIAN);
310 next += 4;
311 }
312
313 void writeDouble(double val) {
314 buffer.setFloat64(next, val, Endianness.LITTLE_ENDIAN);
315 next += 8;
316 }
317
318 void encodePointer(int pointer) {
319 if (pointer == null) {
320 writeUint64(0);
321 return; 161 return;
322 } 162 }
323 int offset = pointer - next; 163 encodePointerToNextUnclaimed(offset);
324 writeUint64(offset); 164 value.encode(this);
325 } 165 }
326 166
327 void grow(int new_size) { 167 Encoder encodePointerArray(int length, int offset, int expectedLength) =>
328 Uint8List new_buffer = new Uint8List(new_size); 168 encoderForArray(kPointerSize, length, offset, expectedLength);
329 new_buffer.setRange(0, buffer.lengthInBytes, buffer.buffer.asUint8List()); 169
330 buffer = new_buffer.buffer.asByteData(); 170 Encoder encoderForArray(
331 } 171 int elementSize, int length, int offset, int expectedLength) {
332 172 if ((expectedLength != kUnspecifiedArrayLength) &&
333 int alloc(int size_request) { 173 (expectedLength != length)) {
334 int pointer = extent; 174 throw 'Trying to encode a fixed array of incorrect length';
335 extent += size_request; 175 }
336 if (extent > buffer.lengthInBytes) { 176 return encoderForArrayByTotalSize(length * elementSize, length, offset);
337 int new_size = buffer.lengthInBytes + size_request; 177 }
338 new_size += new_size ~/ 2; 178
339 grow(new_size); 179 Encoder encoderForArrayByTotalSize(int size, int length, int offset) {
340 } 180 encodePointerToNextUnclaimed(offset);
341 return pointer; 181 return getEncoderAtOffset(
342 } 182 new DataHeader(DataHeader.kHeaderSize + size, length));
343 183 }
344 MojoEncoder createAndEncodeEncoder(int size) { 184
345 int pointer = alloc(align(size)); 185 void encodeBoolArray(
346 encodePointer(pointer); 186 List<bool> value, int offset, int nullability, int expectedLength) {
347 return new MojoEncoder(buffer, handles, pointer, extent); 187 if (value == null) {
348 } 188 encodeNullPointer(offset, isArrayNullable(nullability));
349 189 return;
350 void encodeHandle(core.RawMojoHandle handle) { 190 }
351 if (handle.isValid) { 191 if ((expectedLength != kUnspecifiedArrayLength) &&
352 handles.add(handle); 192 (expectedLength != value.length)) {
353 writeUint32(handles.length - 1); 193 throw 'Trying to encode a fixed array of incorrect size.';
354 } else { 194 }
355 writeUint32(kEncodedInvalidHandleValue); 195 var bytes = new Uint8List((value.length + 7) ~/ kAlignment);
356 } 196 for (int i = 0; i < bytes.length; ++i) {
357 } 197 for (int j = 0; j < kAlignment; ++j) {
358 198 int boolIndex = kAlignment * i + j;
359 void encodeString(String val) { 199 if ((boolIndex < value.length) && value[boolIndex]) {
360 Uint8List utf8string = utf8OfString(val); 200 bytes[i] |= (1 << j);
361 int numElements = utf8string.lengthInBytes;
362 int numBytes = kArrayHeaderSize + numElements;
363 writeUint32(numBytes);
364 writeUint32(numElements);
365 buffer.buffer.asUint8List().setRange(next, next + numElements, utf8string);
366 next += numElements;
367 }
368
369 void encodeArray(Object t, List val, [int numElements, int encodedSize]) {
370 if (numElements == null) {
371 numElements = val.length;
372 }
373 if (encodedSize == null) {
374 encodedSize = kArrayHeaderSize + (getEncodedSize(t) * numElements);
375 }
376
377 writeUint32(encodedSize);
378 writeUint32(numElements);
379
380 if (t == PackedBool) {
381 int b = 0;
382 for (int i = 0; i < numElements; i++) {
383 if (val[i]) {
384 b |= (1 << (i % 8));
385 }
386 if (((i % 8) == 7) || (i == (numElements - 1))) {
387 Uint8.encode(this, b);
388 } 201 }
389 } 202 }
390 } else { 203 }
391 for (int i = 0; i < numElements; i++) { 204 var encoder = encoderForArrayByTotalSize(
392 _callEncode(t, this, val[i]); 205 bytes.length, value.length, offset);
206 encoder.appendUint8Array(bytes);
207 }
208
209 void encodeArray(Function arrayAppend,
210 int elementBytes,
211 List<int> value,
212 int offset,
213 int nullability,
214 int expectedLength) {
215 if (value == null) {
216 encodeNullPointer(offset, isArrayNullable(nullability));
217 return;
218 }
219 var encoder = encoderForArray(
220 elementBytes, value.length, offset, expectedLength);
221 arrayAppend(encoder, value);
222 }
223
224 void encodeInt8Array(
225 List<int> value, int offset, int nullability, int expectedLength) =>
226 encodeArray((e, v) => e.appendInt8Array(v),
227 1, value, offset, nullability, expectedLength);
228
229 void encodeUint8Array(
230 List<int> value, int offset, int nullability, int expectedLength) =>
231 encodeArray((e, v) => e.appendUint8Array(v),
232 1, value, offset, nullability, expectedLength);
233
234 void encodeInt16Array(
235 List<int> value, int offset, int nullability, int expectedLength) =>
236 encodeArray((e, v) => e.appendInt16Array(v),
237 2, value, offset, nullability, expectedLength);
238
239 void encodeUint16Array(
240 List<int> value, int offset, int nullability, int expectedLength) =>
241 encodeArray((e, v) => e.appendUint16Array(v),
242 2, value, offset, nullability, expectedLength);
243
244 void encodeInt32Array(
245 List<int> value, int offset, int nullability, int expectedLength) =>
246 encodeArray((e, v) => e.appendInt32Array(v),
247 4, value, offset, nullability, expectedLength);
248
249 void encodeUint32Array(
250 List<int> value, int offset, int nullability, int expectedLength) =>
251 encodeArray((e, v) => e.appendUint32Array(v),
252 4, value, offset, nullability, expectedLength);
253
254 void encodeInt64Array(
255 List<int> value, int offset, int nullability, int expectedLength) =>
256 encodeArray((e, v) => e.appendInt64Array(v),
257 8, value, offset, nullability, expectedLength);
258
259 void encodeUint64Array(
260 List<int> value, int offset, int nullability, int expectedLength) =>
261 encodeArray((e, v) => e.appendUint64Array(v),
262 8, value, offset, nullability, expectedLength);
263
264 void encodeFloatArray(
265 List<int> value, int offset, int nullability, int expectedLength) =>
266 encodeArray((e, v) => e.appendFloatArray(v),
267 4, value, offset, nullability, expectedLength);
268
269 void encodeDoubleArray(
270 List<int> value, int offset, int nullability, int expectedLength) =>
271 encodeArray((e, v) => e.appendDoubleArray(v),
272 8, value, offset, nullability, expectedLength);
273
274 void encodeHandleArray(List<core.MojoHandle> value,
275 int offset,
276 int nullability,
277 int expectedLength) {
278 if (value == null) {
279 encodeNullPointer(offset, isArrayNullable(nullability));
280 return;
281 }
282 var encoder = encoderForArray(
283 kSerializedHandleSize, value.length, offset, expectedLength);
284 for (int i = 0; i < value.length; ++i) {
285 int handleOffset = DataHeader.kHeaderSize + kSerializedHandleSize * i;
286 encoder.encodeHandle(
287 value[i], handleOffset, isElementNullable(nullability));
288 }
289 }
290
291 static Uint8List _utf8OfString(String s) =>
292 (new Uint8List.fromList((const Utf8Encoder()).convert(s)));
293
294 void encodeString(String value, int offset, bool nullable) {
295 if (value == null) {
296 encodeNullPointer(offset, nullable);
297 return;
298 }
299 int nullability = nullable ? kArrayNullable : kNothingNullable;
300 encodeUint8Array(_utf8OfString(value),
301 offset,
302 nullability,
303 kUnspecifiedArrayLength);
304 }
305
306 void appendBytes(Uint8List value) {
307 _buffer.buffer.buffer.asUint8List().setRange(
308 _base + DataHeader.kHeaderSize,
309 _base + DataHeader.kHeaderSize + value.lengthInBytes,
310 value);
311 }
312
313 void appendInt8Array(List<int> value) =>
314 appendBytes(new Uint8List.view(new Int8List.fromList(value)));
315
316 void appendUint8Array(List<int> value) =>
317 appendBytes(new Uint8List.fromList(value));
318
319 void appendInt16Array(List<int> value) =>
320 appendBytes(new Uint8List.view(new Int16List.fromList(value)));
321
322 void appendUint16Array(List<int> value) =>
323 appendBytes(new Uint8List.view(new Uint16List.fromList(value)));
324
325 void appendInt32Array(List<int> value) =>
326 appendBytes(new Uint8List.view(new Int32List.fromList(value)));
327
328 void appendUint32Array(List<int> value) =>
329 appendBytes(new Uint8List.view(new Uint32List.fromList(value)));
330
331 void appendInt64Array(List<int> value) =>
332 appendBytes(new Uint8List.view(new Int64List.fromList(value)));
333
334 void appendUint64Array(List<int> value) =>
335 appendBytes(new Uint8List.view(new Uint64List.fromList(value)));
336
337 void appendFloatArray(List<int> value) =>
338 appendBytes(new Uint8List.view(new Float32List.fromList(value)));
339
340 void appendDoubleArray(List<int> value) =>
341 appendBytes(new Uint8List.view(new Float64List.fromList(value)));
342
343 Encoder encoderForMap(int offset) {
344 encodePointerToNextUnclaimed(offset);
345 return getEncoderAtOffset(kMapStructHeader);
346 }
347 }
348
349 class Decoder {
350 Message _message;
351 int _base = 0;
352
353 Decoder(this._message, [this._base = 0]);
354
355 Decoder getDecoderAtPosition(int offset) => new Decoder(_message, offset);
356
357 factory Decoder.atOffset(Decoder d, int offset) =>
358 new Decoder(d._message, offset);
359
360 ByteData get _buffer => _message.buffer;
361 List<core.MojoHandle> get _handles => _message.handles;
362
363 int decodeInt8(int offset) => _buffer.getInt8(_base + offset);
364 int decodeUint8(int offset) => _buffer.getUint8(_base + offset);
365 int decodeInt16(int offset) =>
366 _buffer.getInt16(_base + offset, Endianness.LITTLE_ENDIAN);
367 int decodeUint16(int offset) =>
368 _buffer.getUint16(_base + offset, Endianness.LITTLE_ENDIAN);
369 int decodeInt32(int offset) =>
370 _buffer.getInt32(_base + offset, Endianness.LITTLE_ENDIAN);
371 int decodeUint32(int offset) =>
372 _buffer.getUint32(_base + offset, Endianness.LITTLE_ENDIAN);
373 int decodeInt64(int offset) =>
374 _buffer.getInt64(_base + offset, Endianness.LITTLE_ENDIAN);
375 int decodeUint64(int offset) =>
376 _buffer.getUint64(_base + offset,Endianness.LITTLE_ENDIAN);
377 double decodeFloat(int offset) =>
378 _buffer.getFloat32(_base + offset, Endianness.LITTLE_ENDIAN);
379 double decodeDouble(int offset) =>
380 _buffer.getFloat64(_base + offset, Endianness.LITTLE_ENDIAN);
381
382 bool decodeBool(int offset, int bit) =>
383 (decodeUint8(offset) & (1 << bit)) != 0;
384
385 core.MojoHandle decodeHandle(int offset, bool nullable) {
386 int index = decodeInt32(offset);
387 if (index == -1) {
388 if (!nullable) {
389 throw 'Trying to decode an invalid handle from a non-nullable type.';
393 } 390 }
394 } 391 return new core.MojoHandle(core.MojoHandle.INVALID);
395 } 392 }
396 393 return _handles[index];
397 void encodeStruct(Object t, Object val) { 394 }
398 _callEncode(t, this, val); 395
399 } 396 Decoder decodePointer(int offset, bool nullable) {
400 397 int basePosition = _base + offset;
401 void encodeStructPointer(Object t, Object val) { 398 int pointerOffset = decodeUint64(offset);
402 if (val == null) { 399 if (pointerOffset == 0) {
403 encodePointer(val); 400 if (!nullable) {
404 return; 401 throw 'Trying to decode a null pointer for a non-nullable type';
405 } 402 }
406 MojoEncoder encoder = createAndEncodeEncoder(getEncodedSize(t)); 403 return null;
407 _callEncode(t, encoder, val); 404 }
408 extent = encoder.extent; 405 int newPosition = (basePosition + pointerOffset);
409 buffer = encoder.buffer; 406 return new Decoder.atOffset(this, newPosition);
410 } 407 }
411 408
412 void encodeArrayPointer(Object t, List val) { 409 DataHeader decodeDataHeader() {
413 if (val == null) { 410 int size = decodeUint32(DataHeader.kSizeOffset);
414 encodePointer(val); 411 int numFields = decodeUint32(DataHeader.kNumFieldsOffset);
415 return; 412 return new DataHeader(size, numFields);
416 } 413 }
417 int numElements = val.length; 414
418 int encodedSize = kArrayHeaderSize + ((t == PackedBool) ? 415 // Decode arrays.
419 (numElements / 8).ceil() : (getEncodedSize(t) * numElements)); 416 DataHeader decodeDataHeaderForBoolArray(int expectedLength) {
420 MojoEncoder encoder = createAndEncodeEncoder(encodedSize); 417 var header = decodeDataHeader();
421 encoder.encodeArray(t, val, numElements, encodedSize); 418 if (header.size < DataHeader.kHeaderSize + (header.numFields + 7) ~/ 8) {
422 extent = encoder.extent; 419 throw 'Array header is incorrect';
423 buffer = encoder.buffer; 420 }
424 } 421 if ((expectedLength != kUnspecifiedArrayLength) &&
425 422 (header.numFields != expectedLength)) {
426 void encodeStringPointer(String val) { 423 throw 'Incorrect array length';
427 if (val == null) { 424 }
428 encodePointer(val); 425 return header;
429 return; 426 }
430 } 427
431 int encodedSize = kArrayHeaderSize + utf8OfString(val).lengthInBytes; 428 List<bool> decodeBoolArray(int offset, int nullability, int expectedLength) {
432 MojoEncoder encoder = createAndEncodeEncoder(encodedSize); 429 Decoder d = decodePointer(offset, isArrayNullable(nullability));
433 encoder.encodeString(val); 430 if (d == null) {
434 extent = encoder.extent; 431 return null;
435 buffer = encoder.buffer; 432 }
436 } 433 var header = d.decodeDataHeaderForBoolArray(expectedLength);
437 434 var bytes = new Uint8List.view(
438 void encodeMap(Object keyType, Object valType, Map val) { 435 d._buffer.buffer,
439 List keys = val.keys; 436 d._buffer.offsetInBytes + d._base + DataHeader.kHeaderSize,
440 List vals = val.values; 437 (header.numFields + 7) ~/ kAlignment);
441 writeUint32(kStructHeaderSize + kMapStructPayloadSize); 438 var result = new List<bool>(header.numFields);
442 writeUint32(2); 439 for (int i = 0; i < bytes.lengthInBytes; ++i) {
443 encodeArrayPointer(keyType, keys); 440 for (int j = 0; j < kAlignment; ++j) {
444 encodeArrayPointer(valType, vals); 441 int boolIndex = i * kAlignment + j;
445 } 442 if (boolIndex < result.length) {
446 443 result[boolIndex] = (bytes[i] & (1 << j)) != 0;
447 void encodeMapPointer(Object keyTYpe, Object valType, Map val) { 444 }
448 if (val == null) { 445 }
449 encodePointer(val); 446 }
450 return; 447 return result;
451 } 448 }
452 int encodedSize = kStructHeaderSize + kMapStructPayloadSize; 449
453 MojoEncoder encoder = createAndEncodeEncoder(encodedSize); 450 DataHeader decodeDataHeaderForArray(int elementSize, int expectedLength) {
454 encoder.encodeMap(keyType, valType, val); 451 var header = decodeDataHeader();
455 extent = encoder.extent; 452 if (header.size < DataHeader.kHeaderSize + header.numFields * elementSize) {
456 buffer = encoder.buffer; 453 throw 'Array header is incorrect: $header, elementSize = $elementSize';
454 }
455 if ((expectedLength != kUnspecifiedArrayLength) &&
456 (header.numFields != expectedLength)) {
457 throw 'Incorrect array length.';
458 }
459 return header;
460 }
461
462 DataHeader decodeDataHeaderForPointerArray(int expectedLength) =>
463 decodeDataHeaderForArray(kPointerSize, expectedLength);
464
465 List<int> decodeArray(Function arrayViewer,
466 int elementSize,
467 int offset,
468 int nullability,
469 int expectedLength) {
470 Decoder d = decodePointer(offset, isArrayNullable(nullability));
471 if (d == null) {
472 return null;
473 }
474 var header = d.decodeDataHeaderForArray(elementSize, expectedLength);
475 return arrayViewer(
476 d._buffer.buffer,
477 d._buffer.offsetInBytes + d._base + DataHeader.kHeaderSize,
478 header.numFields);
479 }
480
481 List<int> decodeInt8Array(
482 int offset, int nullability, int expectedLength) =>
483 decodeArray((b, s, l) => new Int8List.view(b, s, l),
484 1, offset, nullability, expectedLength);
485
486 List<int> decodeUint8Array(
487 int offset, int nullability, int expectedLength) =>
488 decodeArray((b, s, l) => new Uint8List.view(b, s, l),
489 1, offset, nullability, expectedLength);
490
491 List<int> decodeInt16Array(
492 int offset, int nullability, int expectedLength) =>
493 decodeArray((b, s, l) => new Int16List.view(b, s, l),
494 2, offset, nullability, expectedLength);
495
496 List<int> decodeUint16Array(
497 int offset, int nullability, int expectedLength) =>
498 decodeArray((b, s, l) => new Uint16List.view(b, s, l),
499 2, offset, nullability, expectedLength);
500
501 List<int> decodeInt32Array(
502 int offset, int nullability, int expectedLength) =>
503 decodeArray((b, s, l) => new Int32List.view(b, s, l),
504 4, offset, nullability, expectedLength);
505
506 List<int> decodeUint32Array(
507 int offset, int nullability, int expectedLength) =>
508 decodeArray((b, s, l) => new Uint32List.view(b, s, l),
509 4, offset, nullability, expectedLength);
510
511 List<int> decodeInt64Array(
512 int offset, int nullability, int expectedLength) =>
513 decodeArray((b, s, l) => new Int64List.view(b, s, l),
514 8, offset, nullability, expectedLength);
515
516 List<int> decodeUint64Array(
517 int offset, int nullability, int expectedLength) =>
518 decodeArray((b, s, l) => new Uint64List.view(b, s, l),
519 8, offset, nullability, expectedLength);
520
521 List<double> decodeFloatArray(
522 int offset, int nullability, int expectedLength) =>
523 decodeArray((b, s, l) => new Float32List.view(b, s, l),
524 4, offset, nullability, expectedLength);
525
526 List<double> decodeDoubleArray(
527 int offset, int nullability, int expectedLength) =>
528 decodeArray((b, s, l) => new Float64List.view(b, s, l),
529 8, offset, nullability, expectedLength);
530
531 List<core.MojoHandle> decodeHandleArray(
532 int offset, int nullability, int expectedLength) {
533 Decoder d = decodePointer(offset, isArrayNullable(nullability));
534 if (d == null) {
535 return null;
536 }
537 var header = d.decodeDataHeaderForArray(4, expectedLength);
538 var result = new core.MojoHandle(header.numFields);
539 for (int i = 0; i < result.length; ++i) {
540 result[i] = d.decodeHandle(
541 DataHeader.kHeaderSize + kSerializedHandleSize * i,
542 isElementNullable(nullability));
543 }
544 return result;
545 }
546
547 static String _stringOfUtf8(Uint8List bytes) =>
548 (const Utf8Decoder()).convert(bytes.toList());
549
550 String decodeString(int offset, bool nullable) {
551 int nullability = nullable ? kArrayNullable : 0;
552 var bytes = decodeUint8Array(offset, nullability, kUnspecifiedArrayLength);
553 if (bytes == null) {
554 return null;
555 }
556 return _stringOfUtf8(bytes);
457 } 557 }
458 } 558 }
459
460
461 const int kMessageNameOffset = kStructHeaderSize;
462 const int kMessageFlagsOffset = kMessageNameOffset + 4;
463 const int kMessageRequestIDOffset = kMessageFlagsOffset + 4;
464 const int kMessageExpectsResponse = 1 << 0;
465 const int kMessageIsResponse = 1 << 1;
466
467 class Message {
468 ByteData buffer;
469 List<core.RawMojoHandle> handles;
470
471 Message(this.buffer, this.handles);
472
473 int getHeaderNumBytes() => buffer.getUint32(kStructHeaderNumBytesOffset);
474 int getHeaderNumFields() => buffer.getUint32(kStructHeaderNumFieldsOffset);
475 int getName() => buffer.getUint32(kMessageNameOffset);
476 int getFlags() => buffer.getUint32(kMessageFlagsOffset);
477 bool isResponse() => (getFlags() & kMessageIsResponse) != 0;
478 bool expectsResponse() => (getFlags() & kMessageExpectsResponse) != 0;
479
480 void setRequestID(int id) {
481 buffer.setUint64(kMessageRequestIDOffset, id);
482 }
483 }
484
485
486 class MessageBuilder {
487 MojoEncoder encoder;
488 List<core.RawMojoHandle> handles;
489
490 MessageBuilder._();
491
492 MessageBuilder(int name, int payloadSize) {
493 int numBytes = kMessageHeaderSize + payloadSize;
494 var buffer = new ByteData(numBytes);
495 handles = <core.RawMojoHandle>[];
496
497 encoder = new MojoEncoder(buffer, handles, 0, kMessageHeaderSize);
498 encoder.writeUint32(kMessageHeaderSize);
499 encoder.writeUint32(2); // num_fields;
500 encoder.writeUint32(name);
501 encoder.writeUint32(0); // flags.
502 }
503
504 MojoEncoder createEncoder(int size) {
505 encoder = new MojoEncoder(encoder.buffer,
506 handles,
507 encoder.next,
508 encoder.next + size);
509 return encoder;
510 }
511
512 void encodeStruct(Object t, Object val) {
513 encoder = createEncoder(getEncodedSize(t));
514 _callEncode(t, encoder, val);
515 }
516
517 ByteData _trimBuffer() {
518 return new ByteData.view(encoder.buffer.buffer, 0, encoder.extent);
519 }
520
521 Message finish() {
522 Message message = new Message(_trimBuffer(), handles);
523 encoder = null;
524 handles = null;
525 return message;
526 }
527 }
528
529
530 class MessageWithRequestIDBuilder extends MessageBuilder {
531 MessageWithRequestIDBuilder(
532 int name, int payloadSize, int requestID, [int flags = 0])
533 : super._() {
534 int numBytes = kMessageWithRequestIDHeaderSize + payloadSize;
535 var buffer = new ByteData(numBytes);
536 handles = <core.RawMojoHandle>[];
537
538 encoder = new MojoEncoder(
539 buffer, handles, 0, kMessageWithRequestIDHeaderSize);
540 encoder.writeUint32(kMessageWithRequestIDHeaderSize);
541 encoder.writeUint32(3); // num_fields.
542 encoder.writeUint32(name);
543 encoder.writeUint32(flags);
544 encoder.writeUint64(requestID);
545 }
546 }
547
548
549 class MessageReader {
550 MojoDecoder decoder;
551 int payloadSize;
552 int name;
553 int flags;
554 int requestID;
555
556 MessageReader(Message message) {
557 decoder = new MojoDecoder(message.buffer, message.handles, 0);
558
559 int messageHeaderSize = decoder.readUint32();
560 payloadSize = message.buffer.lengthInBytes - messageHeaderSize;
561
562 int num_fields = decoder.readUint32();
563 name = decoder.readUint32();
564 flags = decoder.readUint32();
565
566 if (num_fields >= 3) {
567 requestID = decoder.readUint64();
568 }
569 decoder.skip(messageHeaderSize - decoder.next);
570 }
571
572 Object decodeStruct(Object t) => _callDecode(t, decoder);
573 }
574
575
576 class PackedBool {}
577
578
579 class Int8 {
580 static const int encodedSize = 1;
581 static int decode(MojoDecoder decoder) => decoder.readInt8();
582 static void encode(MojoEncoder encoder, int val) {
583 encoder.writeInt8(val);
584 }
585 }
586
587
588 class Uint8 {
589 static const int encodedSize = 1;
590 static int decode(MojoDecoder decoder) => decoder.readUint8();
591 static void encode(MojoEncoder encoder, int val) {
592 encoder.writeUint8(val);
593 }
594 }
595
596
597 class Int16 {
598 static const int encodedSize = 2;
599 static int decode(MojoDecoder decoder) => decoder.readInt16();
600 static void encode(MojoEncoder encoder, int val) {
601 encoder.writeInt16(val);
602 }
603 }
604
605
606 class Uint16 {
607 static const int encodedSize = 2;
608 static int decode(MojoDecoder decoder) => decoder.readUint16();
609 static void encode(MojoEncoder encoder, int val) {
610 encoder.writeUint16(val);
611 }
612 }
613
614
615 class Int32 {
616 static const int encodedSize = 4;
617 static int decode(MojoDecoder decoder) => decoder.readInt32();
618 static void encode(MojoEncoder encoder, int val) {
619 encoder.writeInt32(val);
620 }
621 }
622
623
624 class Uint32 {
625 static const int encodedSize = 4;
626 static int decode(MojoDecoder decoder) => decoder.readUint32();
627 static void encode(MojoEncoder encoder, int val) {
628 encoder.writeUint32(val);
629 }
630 }
631
632
633 class Int64 {
634 static const int encodedSize = 8;
635 static int decode(MojoDecoder decoder) => decoder.readInt64();
636 static void encode(MojoEncoder encoder, int val) {
637 encoder.writeInt64(val);
638 }
639 }
640
641
642 class Uint64 {
643 static const int encodedSize = 8;
644 static int decode(MojoDecoder decoder) => decoder.readUint64();
645 static void encode(MojoEncoder encoder, int val) {
646 encoder.writeUint64(val);
647 }
648 }
649
650
651 class MojoString {
652 static const int encodedSize = 8;
653 static String decode(MojoDecoder decoder) => decoder.decodeStringPointer();
654 static void encode(MojoEncoder encoder, String val) {
655 encoder.encodeStringPointer(val);
656 }
657 }
658
659
660 class NullableMojoString {
661 static const int encodedSize = MojoString.encodedSize;
662 static var decode = MojoString.decode;
663 static var encode = MojoString.encode;
664 }
665
666
667 class Float {
668 static const int encodedSize = 4;
669 static double decode(MojoDecoder decoder) => decoder.readFloat();
670 static void encode(MojoEncoder encoder, double val) {
671 encoder.writeFloat(val);
672 }
673 }
674
675
676 class Double {
677 static const int encodedSize = 8;
678 static double decode(MojoDecoder decoder) => decoder.readDouble();
679 static void encode(MojoEncoder encoder, double val) {
680 encoder.writeDouble(val);
681 }
682 }
683
684
685 class PointerTo {
686 Object val;
687
688 PointerTo(this.val);
689
690 int encodedSize = 8;
691 Object decode(MojoDecoder decoder) {
692 int pointer = decoder.decodePointer();
693 if (pointer == 0) {
694 return null;
695 }
696 return _callDecode(val, decoder.decodeAndCreateDecoder(pointer));
697 }
698 void encode(MojoEncoder encoder, Object val) {
699 if (val == null) {
700 encoder.encodePointer(val);
701 return;
702 }
703 MojoEncoder obj_encoder =
704 encoder.createAndEncodeEncoder(getEncodedSize(this.val));
705 _callEncode(this.val, obj_encoder, val);
706 }
707 }
708
709
710 class NullablePointerTo extends PointerTo {
711 NullablePointerTo(Object val) : super(val);
712 }
713
714
715 class ArrayOf {
716 Object val;
717 int length;
718
719 ArrayOf(this.val, [this.length = 0]);
720
721 int dimensions() => [length].addAll((val is ArrayOf) ? val.dimensions() : []);
722
723 int encodedSize = 8;
724 List decode(MojoDecoder decoder) => decoder.decodeArrayPointer(val);
725 void encode(MojoEncoder encoder, List val) {
726 encoder.encodeArrayPointer(this.val, val);
727 }
728 }
729
730
731 class NullableArrayOf extends ArrayOf {
732 NullableArrayOf(Object val, [int length = 0]) : super(val, length);
733 }
734
735
736 class Handle {
737 static const int encodedSize = 4;
738 static core.RawMojoHandle decode(MojoDecoder decoder) =>
739 decoder.decodeHandle();
740 static void encode(MojoEncoder encoder, core.RawMojoHandle val) {
741 encoder.encodeHandle(val);
742 }
743 }
744
745
746 class NullableHandle {
747 static const int encodedSize = Handle.encodedSize;
748 static const decode = Handle.decode;
749 static const encode = Handle.encode;
750 }
751
752
753 class MapOf {
754 Object key;
755 Object val;
756
757 MapOf(this.key, this.val);
758
759 int encodedSize = 8;
760 Map decode(MojoDecoder decoder) => decoder.decodeMapPointer(key, val);
761 void encode(MojoEncoder encoder, Map map) {
762 encoder.encodeMapPointer(key, val, map);
763 }
764 }
765
766
767 class NullableMapOf extends MapOf {
768 NullableMapOf(Object key, Object val) : super(key, val);
769 }
OLDNEW
« no previous file with comments | « mojo/public/dart/src/client.dart ('k') | mojo/public/dart/src/data_pipe.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698