Show More
@@ -49,7 +49,6 b' def serialize_binary_message(msg):' | |||||
49 | bmsg = json.dumps(msg, default=date_default).encode('utf8') |
|
49 | bmsg = json.dumps(msg, default=date_default).encode('utf8') | |
50 | buffers.insert(0, bmsg) |
|
50 | buffers.insert(0, bmsg) | |
51 | nbufs = len(buffers) |
|
51 | nbufs = len(buffers) | |
52 | sizes = (len(buf) for buf in buffers) |
|
|||
53 | offsets = [4 * (nbufs + 1)] |
|
52 | offsets = [4 * (nbufs + 1)] | |
54 | for buf in buffers[:-1]: |
|
53 | for buf in buffers[:-1]: | |
55 | offsets.append(offsets[-1] + len(buf)) |
|
54 | offsets.append(offsets[-1] + len(buf)) |
@@ -12,7 +12,7 b' from IPython.utils.py3compat import string_types' | |||||
12 | from IPython.html.utils import url_path_join, url_escape |
|
12 | from IPython.html.utils import url_path_join, url_escape | |
13 |
|
13 | |||
14 | from ...base.handlers import IPythonHandler, json_errors |
|
14 | from ...base.handlers import IPythonHandler, json_errors | |
15 | from ...base.zmqhandlers import AuthenticatedZMQStreamHandler |
|
15 | from ...base.zmqhandlers import AuthenticatedZMQStreamHandler, deserialize_binary_message | |
16 |
|
16 | |||
17 | from IPython.core.release import kernel_protocol_version |
|
17 | from IPython.core.release import kernel_protocol_version | |
18 |
|
18 | |||
@@ -150,7 +150,10 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):' | |||||
150 | self.log.info("%s closed, closing websocket.", self) |
|
150 | self.log.info("%s closed, closing websocket.", self) | |
151 | self.close() |
|
151 | self.close() | |
152 | return |
|
152 | return | |
153 | msg = json.loads(msg) |
|
153 | if isinstance(msg, bytes): | |
|
154 | msg = deserialize_binary_message(msg) | |||
|
155 | else: | |||
|
156 | msg = json.loads(msg) | |||
154 | self.session.send(self.zmq_stream, msg) |
|
157 | self.session.send(self.zmq_stream, msg) | |
155 |
|
158 | |||
156 | def on_close(self): |
|
159 | def on_close(self): |
@@ -129,12 +129,12 b' define([' | |||||
129 | return this.kernel.send_shell_message("comm_open", content, callbacks, metadata); |
|
129 | return this.kernel.send_shell_message("comm_open", content, callbacks, metadata); | |
130 | }; |
|
130 | }; | |
131 |
|
131 | |||
132 | Comm.prototype.send = function (data, callbacks, metadata) { |
|
132 | Comm.prototype.send = function (data, callbacks, metadata, buffers) { | |
133 | var content = { |
|
133 | var content = { | |
134 | comm_id : this.comm_id, |
|
134 | comm_id : this.comm_id, | |
135 | data : data || {}, |
|
135 | data : data || {}, | |
136 | }; |
|
136 | }; | |
137 | return this.kernel.send_shell_message("comm_msg", content, callbacks, metadata); |
|
137 | return this.kernel.send_shell_message("comm_msg", content, callbacks, metadata, buffers); | |
138 | }; |
|
138 | }; | |
139 |
|
139 | |||
140 | Comm.prototype.close = function (data, callbacks, metadata) { |
|
140 | Comm.prototype.close = function (data, callbacks, metadata) { |
@@ -70,7 +70,7 b' define([' | |||||
70 | /** |
|
70 | /** | |
71 | * @function _get_msg |
|
71 | * @function _get_msg | |
72 | */ |
|
72 | */ | |
73 | Kernel.prototype._get_msg = function (msg_type, content, metadata) { |
|
73 | Kernel.prototype._get_msg = function (msg_type, content, metadata, buffers) { | |
74 | var msg = { |
|
74 | var msg = { | |
75 | header : { |
|
75 | header : { | |
76 | msg_id : utils.uuid(), |
|
76 | msg_id : utils.uuid(), | |
@@ -81,6 +81,7 b' define([' | |||||
81 | }, |
|
81 | }, | |
82 | metadata : metadata || {}, |
|
82 | metadata : metadata || {}, | |
83 | content : content, |
|
83 | content : content, | |
|
84 | buffers : buffers || [], | |||
84 | parent_header : {} |
|
85 | parent_header : {} | |
85 | }; |
|
86 | }; | |
86 | return msg; |
|
87 | return msg; | |
@@ -597,12 +598,12 b' define([' | |||||
597 | * |
|
598 | * | |
598 | * @function send_shell_message |
|
599 | * @function send_shell_message | |
599 | */ |
|
600 | */ | |
600 | Kernel.prototype.send_shell_message = function (msg_type, content, callbacks, metadata) { |
|
601 | Kernel.prototype.send_shell_message = function (msg_type, content, callbacks, metadata, buffers) { | |
601 | if (!this.is_connected()) { |
|
602 | if (!this.is_connected()) { | |
602 | throw new Error("kernel is not connected"); |
|
603 | throw new Error("kernel is not connected"); | |
603 | } |
|
604 | } | |
604 | var msg = this._get_msg(msg_type, content, metadata); |
|
605 | var msg = this._get_msg(msg_type, content, metadata, buffers); | |
605 |
this.channels.shell.send( |
|
606 | this.channels.shell.send(serialize.serialize(msg)); | |
606 | this.set_callbacks_for_msg(msg.header.msg_id, callbacks); |
|
607 | this.set_callbacks_for_msg(msg.header.msg_id, callbacks); | |
607 | return msg.header.msg_id; |
|
608 | return msg.header.msg_id; | |
608 | }; |
|
609 | }; | |
@@ -753,7 +754,7 b' define([' | |||||
753 | }; |
|
754 | }; | |
754 | this.events.trigger('input_reply.Kernel', {kernel: this, content: content}); |
|
755 | this.events.trigger('input_reply.Kernel', {kernel: this, content: content}); | |
755 | var msg = this._get_msg("input_reply", content); |
|
756 | var msg = this._get_msg("input_reply", content); | |
756 |
this.channels.stdin.send( |
|
757 | this.channels.stdin.send(serialize.serialize(msg)); | |
757 | return msg.header.msg_id; |
|
758 | return msg.header.msg_id; | |
758 | }; |
|
759 | }; | |
759 |
|
760 |
@@ -6,42 +6,53 b' define([' | |||||
6 | 'components/utf8/utf8' |
|
6 | 'components/utf8/utf8' | |
7 | ], function ($, utf8) { |
|
7 | ], function ($, utf8) { | |
8 | "use strict"; |
|
8 | "use strict"; | |
9 |
|
9 | |||
10 |
var _deserialize_ |
|
10 | var _deserialize_array_buffer = function (buf) { | |
|
11 | var data = new DataView(buf); | |||
|
12 | // read the header: 1 + nbufs 32b integers | |||
|
13 | var nbufs = data.getInt32(0); | |||
|
14 | var offsets = []; | |||
|
15 | var i; | |||
|
16 | for (i = 1; i <= nbufs; i++) { | |||
|
17 | offsets.push(data.getInt32(i * 4)); | |||
|
18 | } | |||
|
19 | // have to convert array to string for utf8.js | |||
|
20 | var bytestring = String.fromCharCode.apply(null, | |||
|
21 | new Uint8Array(buf.slice(offsets[0], offsets[1])) | |||
|
22 | ); | |||
|
23 | var msg = $.parseJSON( | |||
|
24 | utf8.decode( | |||
|
25 | bytestring | |||
|
26 | ) | |||
|
27 | ); | |||
|
28 | // the remaining chunks are stored as DataViews in msg.buffers | |||
|
29 | msg.buffers = []; | |||
|
30 | var start, stop; | |||
|
31 | for (i = 1; i < nbufs; i++) { | |||
|
32 | start = offsets[i]; | |||
|
33 | stop = offsets[i+1] || buf.byteLength; | |||
|
34 | msg.buffers.push(new DataView(buf.slice(start, stop))); | |||
|
35 | } | |||
|
36 | return msg; | |||
|
37 | }; | |||
|
38 | ||||
|
39 | var _deserialize_binary = function(data, callback) { | |||
11 | // deserialize the binary message format |
|
40 | // deserialize the binary message format | |
12 | // callback will be called with a message whose buffers attribute |
|
41 | // callback will be called with a message whose buffers attribute | |
13 | // will be an array of DataViews. |
|
42 | // will be an array of DataViews. | |
14 | var reader = new FileReader(); |
|
43 | if (data instanceof Blob) { | |
15 | reader.onload = function () { |
|
44 | // data is Blob, have to deserialize from ArrayBuffer in reader callback | |
16 | var buf = this.result; // an ArrayBuffer |
|
45 | var reader = new FileReader(); | |
17 | var data = new DataView(buf); |
|
46 | reader.onload = function () { | |
18 | // read the header: 1 + nbufs 32b integers |
|
47 | var msg = _deserialize_array_buffer(this.result); | |
19 | var nbufs = data.getInt32(0); |
|
48 | callback(msg); | |
20 |
|
|
49 | }; | |
21 | var i; |
|
50 | reader.readAsArrayBuffer(data); | |
22 | for (i = 1; i <= nbufs; i++) { |
|
51 | } else { | |
23 | offsets.push(data.getInt32(i * 4)); |
|
52 | // data is ArrayBuffer, can deserialize directly | |
24 | } |
|
53 | var msg = _deserialize_array_buffer(data); | |
25 | // have to convert array to string for utf8.js |
|
|||
26 | var bytestring = String.fromCharCode.apply(null, |
|
|||
27 | new Uint8Array(buf.slice(offsets[0], offsets[1])) |
|
|||
28 | ); |
|
|||
29 | var msg = $.parseJSON( |
|
|||
30 | utf8.decode( |
|
|||
31 | bytestring |
|
|||
32 | ) |
|
|||
33 | ); |
|
|||
34 | // the remaining chunks are stored as DataViews in msg.buffers |
|
|||
35 | msg.buffers = []; |
|
|||
36 | var start, stop; |
|
|||
37 | for (i = 1; i < nbufs; i++) { |
|
|||
38 | start = offsets[i]; |
|
|||
39 | stop = offsets[i+1] || buf.byteLength; |
|
|||
40 | msg.buffers.push(new DataView(buf.slice(start, stop))); |
|
|||
41 | } |
|
|||
42 | callback(msg); |
|
54 | callback(msg); | |
43 |
} |
|
55 | } | |
44 | reader.readAsArrayBuffer(blob); |
|
|||
45 | }; |
|
56 | }; | |
46 |
|
57 | |||
47 | var deserialize = function (data, callback) { |
|
58 | var deserialize = function (data, callback) { | |
@@ -55,7 +66,63 b' define([' | |||||
55 | } |
|
66 | } | |
56 | }; |
|
67 | }; | |
57 |
|
68 | |||
58 | return { |
|
69 | var _bytes2buf = function (bytestring) { | |
59 | deserialize : deserialize |
|
70 | // convert bytestring to UInt8Array | |
|
71 | var nbytes = bytestring.length; | |||
|
72 | var buf = new Uint8Array(nbytes); | |||
|
73 | for (var i = 0; i < nbytes; i++) { | |||
|
74 | buf[i] = bytestring.charCodeAt(i); | |||
|
75 | } | |||
|
76 | return buf; | |||
|
77 | }; | |||
|
78 | ||||
|
79 | var _serialize_binary = function (msg) { | |||
|
80 | // implement the binary serialization protocol | |||
|
81 | // serializes JSON message to ArrayBuffer | |||
|
82 | msg = $.extend({}, msg); | |||
|
83 | var offsets = []; | |||
|
84 | var buffers = msg.buffers; | |||
|
85 | delete msg.buffers; | |||
|
86 | var json_utf8 = _bytes2buf(utf8.encode(JSON.stringify(msg))); | |||
|
87 | buffers.unshift(json_utf8); | |||
|
88 | var nbufs = buffers.length; | |||
|
89 | offsets.push(4 * (nbufs + 1)); | |||
|
90 | var i; | |||
|
91 | for (i = 0; i + 1 < buffers.length; i++) { | |||
|
92 | offsets.push(offsets[offsets.length-1] + buffers[i].byteLength); | |||
|
93 | } | |||
|
94 | var msg_buf = new Uint8Array( | |||
|
95 | offsets[offsets.length-1] + buffers[buffers.length-1].byteLength | |||
|
96 | ); | |||
|
97 | // use DataView.setInt32 for network byte-order | |||
|
98 | var view = new DataView(msg_buf.buffer); | |||
|
99 | // write nbufs to first 4 bytes | |||
|
100 | view.setInt32(0, nbufs); | |||
|
101 | // write offsets to next 4 * nbufs bytes | |||
|
102 | for (i = 0; i < offsets.length; i++) { | |||
|
103 | view.setInt32(4 * (i+1), offsets[i]); | |||
|
104 | } | |||
|
105 | // write all the buffers at their respective offsets | |||
|
106 | for (i = 0; i < buffers.length; i++) { | |||
|
107 | msg_buf.set(new Uint8Array(buffers[i].buffer), offsets[i]); | |||
|
108 | } | |||
|
109 | ||||
|
110 | // return raw ArrayBuffer | |||
|
111 | return msg_buf.buffer; | |||
|
112 | }; | |||
|
113 | ||||
|
114 | var serialize = function (msg) { | |||
|
115 | console.log(msg.buffers, msg.buffers.length); | |||
|
116 | if (msg.buffers && msg.buffers.length) { | |||
|
117 | return _serialize_binary(msg); | |||
|
118 | } else { | |||
|
119 | return JSON.stringify(msg); | |||
|
120 | } | |||
|
121 | }; | |||
|
122 | ||||
|
123 | var exports = { | |||
|
124 | deserialize : deserialize, | |||
|
125 | serialize: serialize | |||
60 | }; |
|
126 | }; | |
|
127 | return exports; | |||
61 | }); No newline at end of file |
|
128 | }); |
General Comments 0
You need to be logged in to leave comments.
Login now