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

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

Powered by Google App Engine
This is Rietveld 408576698