Binary event #9

Closed
flowersinthesand opened this Issue Mar 5, 2016 · 9 comments

Comments

Projects
None yet
1 participant
@flowersinthesand
Member

flowersinthesand commented Mar 5, 2016

Derived from cettia/cettia-protocol#9

With this feature, you will be able to exchange events whose data is binary without binary-to-text conversion.

  • Find MessagePack JavaScript implementation
  • Implement the default behavior of send method

@flowersinthesand flowersinthesand added this to the 1.0.0-Beta1 milestone Mar 5, 2016

@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

flowersinthesand Mar 6, 2016

Member

msgpack-lite looks the best as MessagePack JavaScript implementation. It is available on browser and Node.js. But, it's too big (37KB minified, 11KB gziped) to include it to cettia.js so those who want to handle binary on browser should include msgpack-lite manually and it should be noted in documentation.

var msgpack = require('msgpack-lite');
var obj = {
  text: "Donghwan Kim",
  binary: new Buffer("Donghwan Kim")
};

var bytes = msgpack.encode(obj);
console.log('[' + new Int8Array(bytes).join(', ') + ']');
console.log(msgpack.decode(bytes));
[-126, -92, 116, 101, 120, 116, -84, 68, 111, 110, 103, 104, 119, 97, 110, 32, 75, 105, 109, -90, 98, 105, 110, 97, 114, 121, -60, 12, 68, 111, 110, 103, 104, 119, 97, 110, 32, 75, 105, 109]
{ text: 'Donghwan Kim',
  binary: <Buffer 44 6f 6e 67 68 77 61 6e 20 4b 69 6d> }

Note that the first line from the result, new Int8Aray(bytes), is the same with one in cettia/cettia-java-server#6 (comment)

Member

flowersinthesand commented Mar 6, 2016

msgpack-lite looks the best as MessagePack JavaScript implementation. It is available on browser and Node.js. But, it's too big (37KB minified, 11KB gziped) to include it to cettia.js so those who want to handle binary on browser should include msgpack-lite manually and it should be noted in documentation.

var msgpack = require('msgpack-lite');
var obj = {
  text: "Donghwan Kim",
  binary: new Buffer("Donghwan Kim")
};

var bytes = msgpack.encode(obj);
console.log('[' + new Int8Array(bytes).join(', ') + ']');
console.log(msgpack.decode(bytes));
[-126, -92, 116, 101, 120, 116, -84, 68, 111, 110, 103, 104, 119, 97, 110, 32, 75, 105, 109, -90, 98, 105, 110, 97, 114, 121, -60, 12, 68, 111, 110, 103, 104, 119, 97, 110, 32, 75, 105, 109]
{ text: 'Donghwan Kim',
  binary: <Buffer 44 6f 6e 67 68 77 61 6e 20 4b 69 6d> }

Note that the first line from the result, new Int8Aray(bytes), is the same with one in cettia/cettia-java-server#6 (comment)

@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

flowersinthesand Mar 6, 2016

Member

On Node, to traverse the given object to check if it contains binary, we can use traverse.

var traverse = require("traverse");
var hasBinary = data => traverse(data).reduce((hasBuffer, e) => {
  return hasBuffer || Buffer.isBuffer(e);
}, false);

console.log(hasBinary("Donghwan Kim"));
console.log(hasBinary(new Buffer("Donghwan Kim")));
false
true

Unfortunately, traverse module is somewhat big to embed in cettia.js. As a trick on browser, using JSON.stringify's replacer option, it's possible to detect if the given object has binary without importing an external module.

var hasBinary = data => {
  var ArrayBuffer = window.ArrayBuffer;
  if (!ArrayBuffer) {
    return false;
  }

  var hasView = false;
  JSON.stringify(data,  (key, value) => {
    hasView = hasView || ArrayBuffer.isView(value);
    return value;
  });
  return hasView;
};

console.log(hasBinary("Donghwan Kim"));
console.log(hasBinary(new TextEncoder().encode("Donghwan Kim")));
false
true

Anyway, if it turns out that it has binary, msgpack.encode should be used and if not JSON.stringify should be used to serialize an event.

Member

flowersinthesand commented Mar 6, 2016

On Node, to traverse the given object to check if it contains binary, we can use traverse.

var traverse = require("traverse");
var hasBinary = data => traverse(data).reduce((hasBuffer, e) => {
  return hasBuffer || Buffer.isBuffer(e);
}, false);

console.log(hasBinary("Donghwan Kim"));
console.log(hasBinary(new Buffer("Donghwan Kim")));
false
true

Unfortunately, traverse module is somewhat big to embed in cettia.js. As a trick on browser, using JSON.stringify's replacer option, it's possible to detect if the given object has binary without importing an external module.

var hasBinary = data => {
  var ArrayBuffer = window.ArrayBuffer;
  if (!ArrayBuffer) {
    return false;
  }

  var hasView = false;
  JSON.stringify(data,  (key, value) => {
    hasView = hasView || ArrayBuffer.isView(value);
    return value;
  });
  return hasView;
};

console.log(hasBinary("Donghwan Kim"));
console.log(hasBinary(new TextEncoder().encode("Donghwan Kim")));
false
true

Anyway, if it turns out that it has binary, msgpack.encode should be used and if not JSON.stringify should be used to serialize an event.

@flowersinthesand flowersinthesand referenced this issue in cettia/cettia-protocol Mar 13, 2016

Closed

Accept typed arrays in send method #10

@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

flowersinthesand Mar 13, 2016

Member
  • Add explanation about binary to socket.send method
  • Add explanation about binary to transport.send method
  • Load msgpack in jsbin example
  • Send binary data in jsbin example
Member

flowersinthesand commented Mar 13, 2016

  • Add explanation about binary to socket.send method
  • Add explanation about binary to transport.send method
  • Load msgpack in jsbin example
  • Send binary data in jsbin example
@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

flowersinthesand Mar 13, 2016

Member
  • Update Node.js compatibility
Member

flowersinthesand commented Mar 13, 2016

  • Update Node.js compatibility
@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

flowersinthesand Mar 13, 2016

Member

In d8576e7 commit, a condition to determine if the current environment is Node.js, typeof exports !== "object", is used too much. It would be better to extract Node.js part so-called node.js and load it in only Node.js environement for performance and size.

Member

flowersinthesand commented Mar 13, 2016

In d8576e7 commit, a condition to determine if the current environment is Node.js, typeof exports !== "object", is used too much. It would be better to extract Node.js part so-called node.js and load it in only Node.js environement for performance and size.

@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

flowersinthesand Mar 16, 2016

Member

JSBin updated to load TextEncoder fallback as well - http://jsbin.com/qaqetibufi/edit?html,js,console

Member

flowersinthesand commented Mar 16, 2016

JSBin updated to load TextEncoder fallback as well - http://jsbin.com/qaqetibufi/edit?html,js,console

@flowersinthesand

This comment has been minimized.

Show comment
Hide comment
@flowersinthesand

flowersinthesand Mar 20, 2016

Member

An explanation about TextEncoder is added - http://jsbin.com/ruquvasevo/edit?html,js,console

Member

flowersinthesand commented Mar 20, 2016

An explanation about TextEncoder is added - http://jsbin.com/ruquvasevo/edit?html,js,console

@flowersinthesand

This comment has been minimized.

Show comment
Hide comment

@flowersinthesand flowersinthesand self-assigned this Feb 11, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment