Binary/Lite

From CommonJS Spec Wiki
Jump to: navigation, search

Philosophy

There are already numerous proposals for Binary datatype out there (Binary/[A-E]). I personally find all of these too complex and cumbersome; aimed at ducktyping and multi-argument-type methods. The Binary/Lite proposal aims to provide a simplified data type which maintains the core functionality.

There is only one object specified in this proposal: the Binary function. It is essentialy a (mutable) array of Numbers. However, when compared with native Array, this object offers these advantages:

  • automatic conversion to Number and masking by 0xFF,
  • flat structure,
  • built-in transcoding methods.


Specification

Construction

The Binary object has only one constructor form.

/**
 * @param {int} length Initial length of this binary
 */
var Binary = exports.Binary = function(length = 0) {};


Correspondence with Array

There is a strong similarity with Array.

Binary.prototype = [];

This way, we automatically have all those iterative methods, such as forEach, reduce etc. On client side, this is achieved by

var Binary = exports.Binary = Array;


Cooperation with other data types

To create Binary from other data types, we use factory methods.

var b1 = Binary.fromArray([1, 2, 3]);
var b2 = Binary.fromString("hello ondřej", "utf-8");

Converting back to standard types is very similar. Note that there are no monkey-patching efforts.

var array = b1.toArray();
var string = b1.decodeToString(charset);

The default "toString" is reserved for debugging purposes.

Binary.prototype.toString = function() {
  return "[Binary " + this.length + "]";
}


Basic usage

The length property specifies the size. It is possible to resize the binary object by assigning to length. Newly created values are zero-filled.

var b1 = Binary.fromArray([1, 2, 3]);
var length = b1.length; /* 3 */
b1.length = 10;

The [] operator is used to retrieve byte values (as Numbers) as well as modify the binary object. One can freely modify non-existant index - in this case, the object is first resized accordingly.

var b1 = Binary.fromArray([1, 2, 3]);
b1[3] = 123; /* b1 == [1, 2, 3, 123] */


Array methods

These methods return a Number and resize the buffer accordingly:

  • pop
  • shift

These methods accept a variadic list of Numbers and resize the buffer accordingly:

  • push
  • unshift

These methods return a Binary:

  • slice
  • splice


Miscellaneous

/**
 * Appends contents of other variadic Binary instance(s) to the end of this one.
 */
Binary.prototype.extendRight = function() {};
/**
 * Appends contents of other variadic Binary instance(s) to the beginning of this one.
 */
Binary.prototype.extendLeft = function() {};
/**
 * Converts contents from one encoding to another
 */
Binary.prototype.transcode = function(fromCharset, toCharset) {};
/**
 * Returns a copy of this Binary
 */
Binary.prototype.clone = function() {};


Place for improvements

Naming

Current naming scheme does not anticipate the existency of an immutable binary data type. If we decide that an immutable binary is a must, I suggest picking one of these approaches:

  • leaving Binary as is, creating an ImmutableBinary type. The awkward name corresponds to the fact that in most situations, a mutable Binary is sufficient.
  • switching back to ByteString and ByteArray variants. I am still unsure what is the overall attitude regarding the number of Binary data types we really want.


Transcoding

As mentioned by MisterN, everything related to transcoding might get separated into a different module. This clearly makes sense, as the set of tasks related to transcoding might get larger in the future. On the other hand, converting Strings to Binary has little sense without specifying a charset to be used.