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

Side by Side Diff: mojo/public/bindings/js/codec.js

Issue 69843003: Implement Mojo message codec in JavaScript (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Aaron's comments Created 7 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 | Annotate | Revision Log
« no previous file with comments | « mojo/mojo.gyp ('k') | mojo/public/bindings/js/codec_unittests.js » ('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 2013 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 define(function() {
6
7 // Memory -------------------------------------------------------------------
8
9 function store8(memory, pointer, val) {
10 memory[pointer] = val;
11 }
12
13 function store16(memory, pointer, val) {
14 memory[pointer + 0] = val >> 0;
15 memory[pointer + 1] = val >> 8;
16 }
17
18 function store32(memory, pointer, val) {
19 memory[pointer + 0] = val >> 0;
20 memory[pointer + 1] = val >> 8;
21 memory[pointer + 2] = val >> 16;
22 memory[pointer + 3] = val >> 24;
23 }
24
25 function store64(memory, pointer, val) {
26 store32(memory, pointer, val);
27 var high = (val / 0x10000) | 0;
28 store32(memory, pointer + 4, high);
29 }
30
31 function load8(memory, pointer) {
32 return memory[pointer];
33 }
34
35 function load16(memory, pointer) {
36 return (memory[pointer + 0] << 0) +
37 (memory[pointer + 1] << 8);
38 }
39
40 function load32(memory, pointer) {
41 return (memory[pointer + 0] << 0) +
42 (memory[pointer + 1] << 8) +
43 (memory[pointer + 2] << 16) +
44 (memory[pointer + 3] << 24);
45 }
46
47 function load64(memory, pointer) {
48 var low = load32(memory, pointer);
49 var high = load32(memory, pointer + 4);
50 return low + high * 0x10000;
51 }
52
53 // Buffer -------------------------------------------------------------------
54
55 function Buffer(size) {
56 this.memory = new Uint8Array(size);
57 this.next = 0;
58 }
59
60 Buffer.prototype.alloc = function(size) {
61 var pointer = this.next;
62 this.next += size;
63 if (this.next > this.memory.length) {
64 var newSize = (1.5 * (this.memory.length + size)) | 0;
65 this.grow(newSize);
66 }
67 return pointer;
68 };
69
70 Buffer.prototype.grow = function(size) {
71 var newMemory = new Uint8Array(size);
72 var oldMemory = this.memory;
73 for (var i = 0; i < oldMemory.length; ++i)
74 newMemory[i] = oldMemory[i];
75 this.memory = newMemory;
76 };
77
78 // Constants ----------------------------------------------------------------
79
80 var kArrayHeaderSize = 8;
81 var kStructHeaderSize = 8;
82 var kMessageHeaderSize = 8;
83
84 // Decoder ------------------------------------------------------------------
85
86 function Decoder(memory, handles, base) {
87 this.memory = memory;
88 this.handles = handles;
89 this.base = base;
90 this.next = base;
91 }
92
93 Decoder.prototype.skip = function(offset) {
94 this.next += offset;
95 };
96
97 Decoder.prototype.read8 = function() {
98 var result = load8(this.memory, this.next);
99 this.next += 1;
100 return result;
101 };
102
103 Decoder.prototype.read32 = function() {
104 var result = load32(this.memory, this.next);
105 this.next += 4;
106 return result;
107 };
108
109 Decoder.prototype.read64 = function() {
110 var result = load64(this.memory, this.next);
111 this.next += 8;
112 return result;
113 };
114
115 Decoder.prototype.decodePointer = function() {
116 // TODO(abarth): To correctly decode a pointer, we need to know the real
117 // base address of the array buffer.
118 var offsetPointer = this.next;
119 var offset = this.read64();
120 if (!offset)
121 return 0;
122 return offsetPointer + offset;
123 };
124
125 Decoder.prototype.decodeAndCreateDecoder = function() {
126 return new Decoder(this.memory, this.handles, this.decodePointer());
127 };
128
129 Decoder.prototype.decodeHandle = function() {
130 return this.handles[this.read32()];
131 };
132
133 Decoder.prototype.decodeString = function() {
134 // TODO(abarth): We should really support UTF-8. We might want to
135 // jump out of the VM to decode the string directly from the array
136 // buffer using v8::String::NewFromUtf8.
137 var numberOfBytes = this.read32();
138 var numberOfElements = this.read32();
139 var val = new Array(numberOfElements);
140 var memory = this.memory;
141 var base = this.next;
142 for (var i = 0; i < numberOfElements; ++i) {
143 val[i] = String.fromCharCode(memory[base + i] & 0x7F);
144 }
145 this.next += numberOfElements;
146 return val.join('');
147 };
148
149 Decoder.prototype.decodeArray = function(cls) {
150 var numberOfBytes = this.read32();
151 var numberOfElements = this.read32();
152 var val = new Array(numberOfElements);
153 for (var i = 0; i < numberOfElements; ++i) {
154 val[i] = cls.decode(this);
155 }
156 return val;
157 };
158
159 Decoder.prototype.decodeStructPointer = function(cls) {
160 return cls.decode(this.decodeAndCreateDecoder());
161 };
162
163 Decoder.prototype.decodeArrayPointer = function(cls) {
164 return this.decodeAndCreateDecoder().decodeArray(cls);
165 };
166
167 Decoder.prototype.decodeStringPointer = function() {
168 return this.decodeAndCreateDecoder().decodeString();
169 };
170
171 // Encoder ------------------------------------------------------------------
172
173 function Encoder(buffer, handles, base) {
174 this.buffer = buffer;
175 this.handles = handles;
176 this.base = base;
177 this.next = base;
178 }
179
180 Encoder.prototype.skip = function(offset) {
181 this.next += offset;
182 };
183
184 Encoder.prototype.write8 = function(val) {
185 store8(this.buffer.memory, this.next, val);
186 this.next += 1;
187 };
188
189 Encoder.prototype.write32 = function(val) {
190 store32(this.buffer.memory, this.next, val);
191 this.next += 4;
192 };
193
194 Encoder.prototype.write64 = function(val) {
195 store64(this.buffer.memory, this.next, val);
196 this.next += 8;
197 };
198
199 Encoder.prototype.encodePointer = function(pointer) {
200 if (!pointer)
201 return this.write64(0);
202 // TODO(abarth): To correctly encode a pointer, we need to know the real
203 // base address of the array buffer.
204 var offset = pointer - this.next;
205 this.write64(offset);
206 };
207
208 Encoder.prototype.createAndEncodeEncoder = function(size) {
209 var pointer = this.buffer.alloc(size);
210 this.encodePointer(pointer);
211 return new Encoder(this.buffer, this.handles, pointer);
212 };
213
214 Encoder.prototype.encodeHandle = function(handle) {
215 this.handles.push(handle);
216 this.write32(this.handles.length - 1);
217 };
218
219 Encoder.prototype.encodeString = function(val) {
220 var numberOfElements = val.length;
221 var numberOfBytes = kArrayHeaderSize + numberOfElements;
222 this.write32(numberOfBytes);
223 this.write32(numberOfElements);
224 // TODO(abarth): We should really support UTF-8. We might want to
225 // jump out of the VM to encode the string directly from the array
226 // buffer using v8::String::WriteUtf8.
227 var memory = this.buffer.memory;
228 var base = this.next;
229 var len = val.length;
230 for (var i = 0; i < len; ++i) {
231 memory[base + i] = val.charCodeAt(i) & 0x7F;
232 }
233 this.next += len;
234 };
235
236 Encoder.prototype.encodeArray = function(cls, val) {
237 var numberOfElements = val.length;
238 var numberOfBytes = kArrayHeaderSize + cls.encodedSize * numberOfElements;
239 this.write32(numberOfBytes);
240 this.write32(numberOfElements);
241 for (var i = 0; i < numberOfElements; ++i) {
242 cls.encode(this, val[i]);
243 }
244 };
245
246 Encoder.prototype.encodeStructPointer = function(cls, val) {
247 var encoder = this.createAndEncodeEncoder(cls.encodedSize);
248 cls.encode(encoder, val);
249 };
250
251 Encoder.prototype.encodeArrayPointer = function(cls, val) {
252 var encodedSize = kArrayHeaderSize + cls.encodedSize * val.length;
253 var encoder = this.createAndEncodeEncoder(encodedSize);
254 encoder.encodeArray(cls, val);
255 };
256
257 Encoder.prototype.encodeStringPointer = function(val) {
258 // TODO(abarth): This won't be right once we support UTF-8.
259 var encodedSize = kArrayHeaderSize + val.length;
260 var encoder = this.createAndEncodeEncoder(encodedSize);
261 encoder.encodeString(val);
262 };
263
264 // Message ------------------------------------------------------------------
265
266 function Message(memory, handles) {
267 this.memory = memory;
268 this.handles = handles;
269 }
270
271 // MessageBuilder -----------------------------------------------------------
272
273 function MessageBuilder(messageName, payloadSize) {
274 var numberOfBytes = kMessageHeaderSize + payloadSize;
275 this.buffer = new Buffer(numberOfBytes);
276 this.handles = [];
277 var encoder = this.createEncoder(kMessageHeaderSize);
278 encoder.write32(numberOfBytes);
279 encoder.write32(messageName);
280 }
281
282 MessageBuilder.prototype.createEncoder = function(size) {
283 var pointer = this.buffer.alloc(size);
284 return new Encoder(this.buffer, this.handles, pointer);
285 }
286
287 MessageBuilder.prototype.encodeStruct = function(cls, val) {
288 cls.encode(this.createEncoder(cls.encodedSize), val);
289 };
290
291 MessageBuilder.prototype.finish = function() {
292 var message = new Message(this.buffer.memory, this.handles);
293 this.buffer = null;
294 this.handles = null;
295 this.encoder = null;
296 return message;
297 };
298
299 // MessageReader ------------------------------------------------------------
300
301 function MessageReader(message) {
302 this.decoder = new Decoder(message.memory, message.handles, 0);
303 this.payloadSize = this.decoder.read32() - kMessageHeaderSize;
304 this.messageName = this.decoder.read32();
305 }
306
307 MessageReader.prototype.decodeStruct = function(cls) {
308 return cls.decode(this.decoder);
309 };
310
311 // Built-in types -----------------------------------------------------------
312
313 function Uint8() {
314 }
315
316 Uint8.encodedSize = 1;
317
318 Uint8.decode = function(decoder) {
319 return decoder.read8();
320 };
321
322 Uint8.encode = function(encoder, val) {
323 encoder.write8(val);
324 };
325
326 function Uint16() {
327 }
328
329 Uint16.encodedSize = 2;
330
331 Uint16.decode = function(decoder) {
332 return decoder.read16();
333 };
334
335 Uint16.encode = function(encoder, val) {
336 encoder.write16(val);
337 };
338
339 function Uint32() {
340 }
341
342 Uint32.encodedSize = 4;
343
344 Uint32.decode = function(decoder) {
345 return decoder.read32();
346 };
347
348 Uint32.encode = function(encoder, val) {
349 encoder.write32(val);
350 };
351
352 function Uint64() {
353 };
354
355 Uint64.encodedSize = 8;
356
357 Uint64.decode = function(decoder) {
358 return decoder.read64();
359 };
360
361 Uint64.encode = function(encoder, val) {
362 encoder.write64(val);
363 };
364
365 function PointerTo(cls) {
366 this.cls = cls;
367 };
368
369 PointerTo.prototype.encodedSize = 8;
370
371 PointerTo.prototype.decode = function(decoder) {
372 return this.cls.decode(decoder.decodeAndCreateDecoder());
373 };
374
375 PointerTo.prototype.encode = function(encoder, val) {
376 var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize);
377 this.cls.encode(objectEncoder, val);
378 };
379
380 function Handle() {
381 }
382
383 Handle.encodedSize = 4;
384
385 Handle.decode = function(decoder) {
386 return decoder.decodeHandle();
387 };
388
389 Handle.encode = function(encoder, val) {
390 encoder.encodeHandle(val);
391 };
392
393 var exports = {};
394 exports.load32 = load32;
395 exports.MessageBuilder = MessageBuilder;
396 exports.MessageReader = MessageReader;
397 exports.kArrayHeaderSize = kArrayHeaderSize;
398 exports.kStructHeaderSize = kStructHeaderSize;
399 exports.kMessageHeaderSize = kMessageHeaderSize;
400 exports.Uint8 = Uint8;
401 exports.Uint16 = Uint16;
402 exports.Uint32 = Uint32;
403 exports.Uint64 = Uint64;
404 exports.PointerTo = PointerTo;
405 exports.Handle = Handle;
406 return exports;
407 });
OLDNEW
« no previous file with comments | « mojo/mojo.gyp ('k') | mojo/public/bindings/js/codec_unittests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698