serialize.js 4.2 KB

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