149 lines
3.7 KiB
JavaScript
149 lines
3.7 KiB
JavaScript
|
|
||
|
function ArrayBufferSer(type, data, options) {
|
||
|
if(type === undefined) throw "ArrayBufferSer should be created with a type";
|
||
|
this.options = options || {}
|
||
|
this._initFunctions();
|
||
|
this.headerSize = 8;
|
||
|
this.data = data;
|
||
|
this.type = type = Math.min(type, ArrayBufferSer.BUFFER);
|
||
|
var size = this._sizeFor(this.headerSize, data);
|
||
|
this.buffer = new Buffer(this.headerSize + size);
|
||
|
this.buffer.writeUInt32BE(type, 0); // this could be one byte but for byte padding is better to be 4 bytes
|
||
|
this.buffer.writeUInt32BE(size, 4);
|
||
|
this.offset = this.headerSize;
|
||
|
|
||
|
var w = this.writeFn[type];
|
||
|
|
||
|
if(!this.options.delta) {
|
||
|
for(var i = 0; i < data.length; ++i) {
|
||
|
this[w](data[i]);
|
||
|
}
|
||
|
} else {
|
||
|
this[w](data[0]);
|
||
|
for(var i = 1; i < data.length; ++i) {
|
||
|
this[w](data[i] - data[i - 1]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// constants
|
||
|
//
|
||
|
ArrayBufferSer.INT8 = 1;
|
||
|
ArrayBufferSer.UINT8 = 2;
|
||
|
ArrayBufferSer.UINT8_CLAMP = 3;
|
||
|
ArrayBufferSer.INT16 = 4;
|
||
|
ArrayBufferSer.UINT16 = 5;
|
||
|
ArrayBufferSer.INT32 = 6;
|
||
|
ArrayBufferSer.UINT32 = 7;
|
||
|
ArrayBufferSer.FLOAT32 = 8;
|
||
|
//ArrayBufferSer.FLOAT64 = 9; not supported
|
||
|
ArrayBufferSer.STRING = 10;
|
||
|
ArrayBufferSer.BUFFER = 11;
|
||
|
|
||
|
ArrayBufferSer.MAX_PADDING = ArrayBufferSer.INT32;
|
||
|
|
||
|
|
||
|
ArrayBufferSer.typeNames = {
|
||
|
'int8': ArrayBufferSer.INT8,
|
||
|
'uint8': ArrayBufferSer.UINT8,
|
||
|
'uintclamp': ArrayBufferSer.UINT8_CLAMP,
|
||
|
'int16': ArrayBufferSer.INT16,
|
||
|
'uint16': ArrayBufferSer.UINT16,
|
||
|
'int32': ArrayBufferSer.INT32,
|
||
|
'uint32': ArrayBufferSer.UINT32,
|
||
|
'float32': ArrayBufferSer.FLOAT32,
|
||
|
'string': ArrayBufferSer.STRING,
|
||
|
'buffer': ArrayBufferSer.BUFFER
|
||
|
};
|
||
|
|
||
|
ArrayBufferSer.prototype = {
|
||
|
|
||
|
// 0 not used
|
||
|
sizes: [NaN, 1, 1, 1, 2, 2, 4, 4, 4, 8],
|
||
|
|
||
|
_paddingFor: function(off, type) {
|
||
|
var s = this.sizes[type]
|
||
|
if(s) {
|
||
|
var r = off % s;
|
||
|
return r == 0 ? 0 : s - r;
|
||
|
}
|
||
|
return 0;
|
||
|
},
|
||
|
|
||
|
_sizeFor: function(offset, t) {
|
||
|
var self = this;
|
||
|
var s = this.sizes[this.type]
|
||
|
if(s) {
|
||
|
return s*t.length;
|
||
|
}
|
||
|
s = 0;
|
||
|
if(this.type == ArrayBufferSer.STRING) {
|
||
|
// calculate size with padding
|
||
|
t.forEach(function(arr) {
|
||
|
var pad = self._paddingFor(offset, ArrayBufferSer.MAX_PADDING);
|
||
|
s += pad;
|
||
|
offset += pad;
|
||
|
var len = (self.headerSize + arr.length*2)
|
||
|
s += len;
|
||
|
offset += len;
|
||
|
});
|
||
|
} else {
|
||
|
t.forEach(function(arr) {
|
||
|
var pad = self._paddingFor(offset, ArrayBufferSer.MAX_PADDING);
|
||
|
s += pad;
|
||
|
offset += pad;
|
||
|
s += arr.getSize()
|
||
|
offset += arr.getSize();
|
||
|
});
|
||
|
}
|
||
|
return s;
|
||
|
},
|
||
|
|
||
|
getDataSize: function() {
|
||
|
return this._sizeFor(0, this.data);
|
||
|
},
|
||
|
|
||
|
getSize: function() {
|
||
|
return this.headerSize + this._sizeFor(this.headerSize, this.data);
|
||
|
},
|
||
|
|
||
|
writeFn: ['', 'writeInt8', 'writeUInt8','writeUInt8Clamp', 'writeInt16LE', 'writeUInt16LE', 'writeUInt32LE', 'writeUInt32LE', 'writeFloatLE', 'writeDoubleLE', 'writeString', 'writteBuffer'],
|
||
|
|
||
|
_initFunctions: function() {
|
||
|
var self = this;
|
||
|
this.writeFn.forEach(function(fn) {
|
||
|
if(self[fn] === undefined)
|
||
|
self[fn] = function(d) {
|
||
|
self.buffer[fn](d, self.offset);
|
||
|
self.offset += self.sizes[self.type];
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
writeUInt8Clamp: function(c) {
|
||
|
this.buffer.writeUInt8(Math.min(255, c), this.offset);
|
||
|
this.offset += 1;
|
||
|
},
|
||
|
|
||
|
writeString: function(s) {
|
||
|
var arr = [];
|
||
|
for(var i = 0, len = s.length; i < len; ++i) {
|
||
|
arr.push(s.charCodeAt(i));
|
||
|
}
|
||
|
var str = new ArrayBufferSer(ArrayBufferSer.UINT16, arr);
|
||
|
this.writteBuffer(str);
|
||
|
},
|
||
|
|
||
|
writteBuffer: function(b) {
|
||
|
this.offset += this._paddingFor(this.offset, ArrayBufferSer.MAX_PADDING);
|
||
|
// copy header
|
||
|
b.buffer.copy(this.buffer, this.offset)
|
||
|
this.offset += b.buffer.length;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
module.exports = ArrayBufferSer;
|