serialize.js
126 lines
| 4.2 KiB
| application/javascript
|
JavascriptLexer
MinRK
|
r18331 | // Copyright (c) IPython Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||||
define([ | ||||
MinRK
|
r18416 | 'underscore', | ||
], function (_) { | ||||
MinRK
|
r18331 | "use strict"; | ||
MinRK
|
r18332 | |||
var _deserialize_array_buffer = function (buf) { | ||||
var data = new DataView(buf); | ||||
// read the header: 1 + nbufs 32b integers | ||||
MinRK
|
r18338 | var nbufs = data.getUint32(0); | ||
MinRK
|
r18332 | var offsets = []; | ||
var i; | ||||
for (i = 1; i <= nbufs; i++) { | ||||
MinRK
|
r18338 | offsets.push(data.getUint32(i * 4)); | ||
MinRK
|
r18332 | } | ||
MinRK
|
r18333 | var json_bytes = new Uint8Array(buf.slice(offsets[0], offsets[1])); | ||
MinRK
|
r18416 | var msg = JSON.parse( | ||
MinRK
|
r18333 | (new TextDecoder('utf8')).decode(json_bytes) | ||
MinRK
|
r18332 | ); | ||
// the remaining chunks are stored as DataViews in msg.buffers | ||||
msg.buffers = []; | ||||
var start, stop; | ||||
for (i = 1; i < nbufs; i++) { | ||||
start = offsets[i]; | ||||
stop = offsets[i+1] || buf.byteLength; | ||||
msg.buffers.push(new DataView(buf.slice(start, stop))); | ||||
} | ||||
return msg; | ||||
}; | ||||
Jason Grout
|
r20441 | var _deserialize_binary = function(data) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* deserialize the binary message format | ||||
* callback will be called with a message whose buffers attribute | ||||
* will be an array of DataViews. | ||||
*/ | ||||
MinRK
|
r18332 | if (data instanceof Blob) { | ||
// data is Blob, have to deserialize from ArrayBuffer in reader callback | ||||
var reader = new FileReader(); | ||||
Jason Grout
|
r20441 | var promise = new Promise(function(resolve, reject) { | ||
reader.onload = function () { | ||||
var msg = _deserialize_array_buffer(this.result); | ||||
resolve(msg); | ||||
}; | ||||
}); | ||||
MinRK
|
r18332 | reader.readAsArrayBuffer(data); | ||
Jason Grout
|
r20441 | return promise; | ||
MinRK
|
r18332 | } else { | ||
// data is ArrayBuffer, can deserialize directly | ||||
var msg = _deserialize_array_buffer(data); | ||||
Jason Grout
|
r20441 | return msg; | ||
MinRK
|
r18332 | } | ||
MinRK
|
r18331 | }; | ||
Jason Grout
|
r20441 | var deserialize = function (data) { | ||
Jonathan Frederic
|
r19176 | /** | ||
Jason Grout
|
r20441 | * deserialize a message and return a promise for the unpacked message | ||
Jonathan Frederic
|
r19176 | */ | ||
MinRK
|
r18331 | if (typeof data === "string") { | ||
// text JSON message | ||||
Jason Grout
|
r20441 | return Promise.resolve(JSON.parse(data)); | ||
MinRK
|
r18331 | } else { | ||
// binary message | ||||
Jason Grout
|
r20441 | return Promise.resolve(_deserialize_binary(data)); | ||
MinRK
|
r18331 | } | ||
}; | ||||
MinRK
|
r18332 | var _serialize_binary = function (msg) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* implement the binary serialization protocol | ||||
* serializes JSON message to ArrayBuffer | ||||
*/ | ||||
MinRK
|
r18416 | msg = _.clone(msg); | ||
MinRK
|
r18332 | var offsets = []; | ||
MinRK
|
r18337 | var buffers = []; | ||
Jason Grout
|
r20824 | var i; | ||
for (i = 0; i < msg.buffers.length; i++) { | ||||
// msg.buffers elements could be either views or ArrayBuffers | ||||
// buffers elements are ArrayBuffers | ||||
Jason Grout
|
r20829 | var b = msg.buffers[i]; | ||
buffers.push(b.buffer instanceof ArrayBuffer ? b.buffer : b); | ||||
Jason Grout
|
r20824 | } | ||
MinRK
|
r18332 | delete msg.buffers; | ||
MinRK
|
r18333 | var json_utf8 = (new TextEncoder('utf8')).encode(JSON.stringify(msg)); | ||
MinRK
|
r18332 | buffers.unshift(json_utf8); | ||
var nbufs = buffers.length; | ||||
offsets.push(4 * (nbufs + 1)); | ||||
for (i = 0; i + 1 < buffers.length; i++) { | ||||
offsets.push(offsets[offsets.length-1] + buffers[i].byteLength); | ||||
} | ||||
var msg_buf = new Uint8Array( | ||||
offsets[offsets.length-1] + buffers[buffers.length-1].byteLength | ||||
); | ||||
MinRK
|
r18338 | // use DataView.setUint32 for network byte-order | ||
MinRK
|
r18332 | var view = new DataView(msg_buf.buffer); | ||
// write nbufs to first 4 bytes | ||||
MinRK
|
r18338 | view.setUint32(0, nbufs); | ||
MinRK
|
r18332 | // write offsets to next 4 * nbufs bytes | ||
for (i = 0; i < offsets.length; i++) { | ||||
MinRK
|
r18338 | view.setUint32(4 * (i+1), offsets[i]); | ||
MinRK
|
r18332 | } | ||
// write all the buffers at their respective offsets | ||||
for (i = 0; i < buffers.length; i++) { | ||||
Jason Grout
|
r20824 | msg_buf.set(new Uint8Array(buffers[i]), offsets[i]); | ||
MinRK
|
r18332 | } | ||
// return raw ArrayBuffer | ||||
return msg_buf.buffer; | ||||
}; | ||||
var serialize = function (msg) { | ||||
if (msg.buffers && msg.buffers.length) { | ||||
return _serialize_binary(msg); | ||||
} else { | ||||
return JSON.stringify(msg); | ||||
} | ||||
}; | ||||
var exports = { | ||||
deserialize : deserialize, | ||||
serialize: serialize | ||||
MinRK
|
r18331 | }; | ||
MinRK
|
r18332 | return exports; | ||
Jason Grout
|
r20441 | }); | ||