
/** Binary encoder
 *
 * This module encodes scalar data from a grid-like source
 * into a packed binary format for bandwidth efficiency and
 * speed of access.
 *
 * Data are indexed by i & j values, with "i" being constant
 * (e.g., a sequence or line number) and "j" expected to change
 * by a constant, linear amount (e.g., point numbers). All data
 * from consecutive "j" values will be encoded as a single array
 * (or series of arrays if multiple values are encoded).
 * If there is a jump in the "j" progression, a new "chunk" will
 * be started with a new array (or series of arrays).
 *
 * Multiple values may be encoded per (i, j) pair, using any of
 * the types supported by JavaScript's TypedArray except for
 * Float16 and Uint8Clamped. Each variable can be encoded with
 * a different size.
 *
 * Values may be encoded directly or as deltas from an initial
 * value. The latter is particularly efficient when dealing with
 * monotonically incrementing data, such as timestamps.
 *
 * The conceptual packet format for sequentially encoded data
 * looks like this:
 *
 * <msg-type> <count: x> <i> <j0> <Δj>
 *
 * <Δelement_count: y>
 * <element_count: z>
 *
 * <Δelement_1_type_base> … <Δelement_y_type_base>
 * <Δelement_1_type_incr> … <Δelement_y_type_incr>
 * <elem_1_type> … <elem_z_type>
 *
 * <Δelement_1_first> … <Δelement_z_first>
 *
 * <Δelem_1_0> … <Δelem_1_x>
 * …
 * <Δelem_y_0> … <Δelem_y_x>
 * <elem_1_0> … <elem_1_x>
 * …
 * <elem_z_0> … <elem_z_x>
 *
 *
 * The conceptual packet format for interleaved encoded data
 * looks like this:
 *
 *
 * <msg-type> <count: x> <i> <j0> <Δj>
 *
 * <Δelement_count: y>
 * <element_count: z>
 *
 * <Δelement_1_type_base> … <Δelement_y_type_base>
 * <Δelement_1_type_incr> … <Δelement_y_type_incr>
 * <elem_1_type> … <elem_z_type>
 *
 * <Δelement_1_first> … <Δelement_y_first>
 *
 * <Δelem_1_0> <Δelem_2_0> … <Δelem_y_0> <elem_1_0> <elem_2_0> … <elem_z_0>
 * <Δelem_1_1> <Δelem_2_1> … <Δelem_y_1> <elem_1_1> <elem_2_1> … <elem_z_1>
 * …
 * <Δelem_1_x> <Δelem_2_x> … <Δelem_y_x> <elem_1_x> <elem_2_x> … <elem_z_x>
 *
 *
 * Usage example:
 *
 * json = [
 *   {
 *     sequence: 7,
 *     sailline: 5354,
 *     line: 5356,
 *     point: 1068,
 *     tstamp: 1695448704372,
 *     objrefraw: 3,
 *     objreffinal: 4
 *   },
 *   {
 *     sequence: 7,
 *     sailline: 5354,
 *     line: 5352,
 *     point: 1070,
 *     tstamp: 1695448693612,
 *     objrefraw: 2,
 *     objreffinal: 3
 *   },
 *   {
 *     sequence: 7,
 *     sailline: 5354,
 *     line: 5356,
 *     point: 1072,
 *     tstamp: 1695448684624,
 *     objrefraw: 3,
 *     objreffinal: 4
 *   }
 * ];
 *
 * deltas = [
 *   { key: el => el.tstamp, baseType: BigUint64Array, incrType: Int16Array }
 * ];
 *
 * elems = [
 *   { key: el => el.objrefraw, type: Uint8Array },
 *   { key: el => el.objreffinal, type: Uint8Array }
 * ];
 *
 * i = el => el.sequence;
 *
 * j = el => el.point;
 *
 * bundle = encode(json, i, j, deltas, elems);
 *
 * // bundle:
 *
 * Uint8Array(40) [
 *    36,   0,   0,  28, 17, 0,  3, 0, 7,   0,
 *    44,   4,   2,   0,  1, 2, 42, 1, 1, 116,
 *    37, 158, 192, 138,  1, 0,  0, 0, 0,   0,
 *   248, 213, 228, 220,  3, 2,  3, 4, 3,   4
 * ]
 *
 * decode(bundle);
 *
 * {
 *   i: 7,
 *   j: [ 1068, 1070, 1072 ],
 *   'Δelems': [ [ 1695448704372, 1695448693612, 1695448684624 ] ],
 *   elems: [ [ 3, 2, 3 ], [ 4, 3, 4 ] ]
 * }
 *
 */

module.exports = {
	encode: {...require('./encode')},
	decode: {...require('./decode')},
	...require('./classes')
};
