binary.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { isBinary } from "./is-binary.js";
  2. /**
  3. * Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.
  4. *
  5. * @param {Object} packet - socket.io event packet
  6. * @return {Object} with deconstructed packet and list of buffers
  7. * @public
  8. */
  9. export function deconstructPacket(packet) {
  10. const buffers = [];
  11. const packetData = packet.data;
  12. const pack = packet;
  13. pack.data = _deconstructPacket(packetData, buffers);
  14. pack.attachments = buffers.length; // number of binary 'attachments'
  15. return { packet: pack, buffers: buffers };
  16. }
  17. function _deconstructPacket(data, buffers) {
  18. if (!data)
  19. return data;
  20. if (isBinary(data)) {
  21. const placeholder = { _placeholder: true, num: buffers.length };
  22. buffers.push(data);
  23. return placeholder;
  24. }
  25. else if (Array.isArray(data)) {
  26. const newData = new Array(data.length);
  27. for (let i = 0; i < data.length; i++) {
  28. newData[i] = _deconstructPacket(data[i], buffers);
  29. }
  30. return newData;
  31. }
  32. else if (typeof data === "object" && !(data instanceof Date)) {
  33. const newData = {};
  34. for (const key in data) {
  35. if (Object.prototype.hasOwnProperty.call(data, key)) {
  36. newData[key] = _deconstructPacket(data[key], buffers);
  37. }
  38. }
  39. return newData;
  40. }
  41. return data;
  42. }
  43. /**
  44. * Reconstructs a binary packet from its placeholder packet and buffers
  45. *
  46. * @param {Object} packet - event packet with placeholders
  47. * @param {Array} buffers - binary buffers to put in placeholder positions
  48. * @return {Object} reconstructed packet
  49. * @public
  50. */
  51. export function reconstructPacket(packet, buffers) {
  52. packet.data = _reconstructPacket(packet.data, buffers);
  53. delete packet.attachments; // no longer useful
  54. return packet;
  55. }
  56. function _reconstructPacket(data, buffers) {
  57. if (!data)
  58. return data;
  59. if (data && data._placeholder === true) {
  60. const isIndexValid = typeof data.num === "number" &&
  61. data.num >= 0 &&
  62. data.num < buffers.length;
  63. if (isIndexValid) {
  64. return buffers[data.num]; // appropriate buffer (should be natural order anyway)
  65. }
  66. else {
  67. throw new Error("illegal attachments");
  68. }
  69. }
  70. else if (Array.isArray(data)) {
  71. for (let i = 0; i < data.length; i++) {
  72. data[i] = _reconstructPacket(data[i], buffers);
  73. }
  74. }
  75. else if (typeof data === "object") {
  76. for (const key in data) {
  77. if (Object.prototype.hasOwnProperty.call(data, key)) {
  78. data[key] = _reconstructPacket(data[key], buffers);
  79. }
  80. }
  81. }
  82. return data;
  83. }