##// END OF EJS Templates
Make it possible for msg.buffers in javascript to be either ArrayBuffers or views
Jason Grout -
Show More
@@ -1,123 +1,125 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 'underscore',
5 'underscore',
6 ], function (_) {
6 ], function (_) {
7 "use strict";
7 "use strict";
8
8
9 var _deserialize_array_buffer = function (buf) {
9 var _deserialize_array_buffer = function (buf) {
10 var data = new DataView(buf);
10 var data = new DataView(buf);
11 // read the header: 1 + nbufs 32b integers
11 // read the header: 1 + nbufs 32b integers
12 var nbufs = data.getUint32(0);
12 var nbufs = data.getUint32(0);
13 var offsets = [];
13 var offsets = [];
14 var i;
14 var i;
15 for (i = 1; i <= nbufs; i++) {
15 for (i = 1; i <= nbufs; i++) {
16 offsets.push(data.getUint32(i * 4));
16 offsets.push(data.getUint32(i * 4));
17 }
17 }
18 var json_bytes = new Uint8Array(buf.slice(offsets[0], offsets[1]));
18 var json_bytes = new Uint8Array(buf.slice(offsets[0], offsets[1]));
19 var msg = JSON.parse(
19 var msg = JSON.parse(
20 (new TextDecoder('utf8')).decode(json_bytes)
20 (new TextDecoder('utf8')).decode(json_bytes)
21 );
21 );
22 // the remaining chunks are stored as DataViews in msg.buffers
22 // the remaining chunks are stored as DataViews in msg.buffers
23 msg.buffers = [];
23 msg.buffers = [];
24 var start, stop;
24 var start, stop;
25 for (i = 1; i < nbufs; i++) {
25 for (i = 1; i < nbufs; i++) {
26 start = offsets[i];
26 start = offsets[i];
27 stop = offsets[i+1] || buf.byteLength;
27 stop = offsets[i+1] || buf.byteLength;
28 msg.buffers.push(new DataView(buf.slice(start, stop)));
28 msg.buffers.push(new DataView(buf.slice(start, stop)));
29 }
29 }
30 return msg;
30 return msg;
31 };
31 };
32
32
33 var _deserialize_binary = function(data) {
33 var _deserialize_binary = function(data) {
34 /**
34 /**
35 * deserialize the binary message format
35 * deserialize the binary message format
36 * callback will be called with a message whose buffers attribute
36 * callback will be called with a message whose buffers attribute
37 * will be an array of DataViews.
37 * will be an array of DataViews.
38 */
38 */
39 if (data instanceof Blob) {
39 if (data instanceof Blob) {
40 // data is Blob, have to deserialize from ArrayBuffer in reader callback
40 // data is Blob, have to deserialize from ArrayBuffer in reader callback
41 var reader = new FileReader();
41 var reader = new FileReader();
42 var promise = new Promise(function(resolve, reject) {
42 var promise = new Promise(function(resolve, reject) {
43 reader.onload = function () {
43 reader.onload = function () {
44 var msg = _deserialize_array_buffer(this.result);
44 var msg = _deserialize_array_buffer(this.result);
45 resolve(msg);
45 resolve(msg);
46 };
46 };
47 });
47 });
48 reader.readAsArrayBuffer(data);
48 reader.readAsArrayBuffer(data);
49 return promise;
49 return promise;
50 } else {
50 } else {
51 // data is ArrayBuffer, can deserialize directly
51 // data is ArrayBuffer, can deserialize directly
52 var msg = _deserialize_array_buffer(data);
52 var msg = _deserialize_array_buffer(data);
53 return msg;
53 return msg;
54 }
54 }
55 };
55 };
56
56
57 var deserialize = function (data) {
57 var deserialize = function (data) {
58 /**
58 /**
59 * deserialize a message and return a promise for the unpacked message
59 * deserialize a message and return a promise for the unpacked message
60 */
60 */
61 if (typeof data === "string") {
61 if (typeof data === "string") {
62 // text JSON message
62 // text JSON message
63 return Promise.resolve(JSON.parse(data));
63 return Promise.resolve(JSON.parse(data));
64 } else {
64 } else {
65 // binary message
65 // binary message
66 return Promise.resolve(_deserialize_binary(data));
66 return Promise.resolve(_deserialize_binary(data));
67 }
67 }
68 };
68 };
69
69
70 var _serialize_binary = function (msg) {
70 var _serialize_binary = function (msg) {
71 /**
71 /**
72 * implement the binary serialization protocol
72 * implement the binary serialization protocol
73 * serializes JSON message to ArrayBuffer
73 * serializes JSON message to ArrayBuffer
74 */
74 */
75 msg = _.clone(msg);
75 msg = _.clone(msg);
76 var offsets = [];
76 var offsets = [];
77 var buffers = [];
77 var buffers = [];
78 msg.buffers.map(function (buf) {
78 var i;
79 buffers.push(buf);
79 for (i = 0; i < msg.buffers.length; i++) {
80 });
80 // msg.buffers elements could be either views or ArrayBuffers
81 // buffers elements are ArrayBuffers
82 buffers.push(msg.buffers[i].buffer || msg.buffers[i])
83 }
81 delete msg.buffers;
84 delete msg.buffers;
82 var json_utf8 = (new TextEncoder('utf8')).encode(JSON.stringify(msg));
85 var json_utf8 = (new TextEncoder('utf8')).encode(JSON.stringify(msg));
83 buffers.unshift(json_utf8);
86 buffers.unshift(json_utf8);
84 var nbufs = buffers.length;
87 var nbufs = buffers.length;
85 offsets.push(4 * (nbufs + 1));
88 offsets.push(4 * (nbufs + 1));
86 var i;
87 for (i = 0; i + 1 < buffers.length; i++) {
89 for (i = 0; i + 1 < buffers.length; i++) {
88 offsets.push(offsets[offsets.length-1] + buffers[i].byteLength);
90 offsets.push(offsets[offsets.length-1] + buffers[i].byteLength);
89 }
91 }
90 var msg_buf = new Uint8Array(
92 var msg_buf = new Uint8Array(
91 offsets[offsets.length-1] + buffers[buffers.length-1].byteLength
93 offsets[offsets.length-1] + buffers[buffers.length-1].byteLength
92 );
94 );
93 // use DataView.setUint32 for network byte-order
95 // use DataView.setUint32 for network byte-order
94 var view = new DataView(msg_buf.buffer);
96 var view = new DataView(msg_buf.buffer);
95 // write nbufs to first 4 bytes
97 // write nbufs to first 4 bytes
96 view.setUint32(0, nbufs);
98 view.setUint32(0, nbufs);
97 // write offsets to next 4 * nbufs bytes
99 // write offsets to next 4 * nbufs bytes
98 for (i = 0; i < offsets.length; i++) {
100 for (i = 0; i < offsets.length; i++) {
99 view.setUint32(4 * (i+1), offsets[i]);
101 view.setUint32(4 * (i+1), offsets[i]);
100 }
102 }
101 // write all the buffers at their respective offsets
103 // write all the buffers at their respective offsets
102 for (i = 0; i < buffers.length; i++) {
104 for (i = 0; i < buffers.length; i++) {
103 msg_buf.set(new Uint8Array(buffers[i].buffer), offsets[i]);
105 msg_buf.set(new Uint8Array(buffers[i]), offsets[i]);
104 }
106 }
105
107
106 // return raw ArrayBuffer
108 // return raw ArrayBuffer
107 return msg_buf.buffer;
109 return msg_buf.buffer;
108 };
110 };
109
111
110 var serialize = function (msg) {
112 var serialize = function (msg) {
111 if (msg.buffers && msg.buffers.length) {
113 if (msg.buffers && msg.buffers.length) {
112 return _serialize_binary(msg);
114 return _serialize_binary(msg);
113 } else {
115 } else {
114 return JSON.stringify(msg);
116 return JSON.stringify(msg);
115 }
117 }
116 };
118 };
117
119
118 var exports = {
120 var exports = {
119 deserialize : deserialize,
121 deserialize : deserialize,
120 serialize: serialize
122 serialize: serialize
121 };
123 };
122 return exports;
124 return exports;
123 });
125 });
General Comments 0
You need to be logged in to leave comments. Login now