Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Metaview - A tiny, fast, simplified abstraction of JS DataViews (similar to AS3's ByteArray)
// writing
var o = new MetaView();
o.writeInt16(-128);
o.writeUint16(128);
o.writeFloat32(3.141592);
o.writeFloat32([1.5, 1.5]);
o.writeUTF8String("räksmörgås");
// saving
var s = o.finalize();
// reading
var i = new MetaView(s);
console.log(i.readInt16());
console.log(i.readUint16());
console.log(i.readFloat32());
console.log(i.readFloat32(2));
console.log(i.readUTF8String());
// polyfill for Array.transfer
if (!ArrayBuffer.transfer)
ArrayBuffer.transfer = function (oldBuffer, newLength) {
newLength = newLength || oldBuffer.byteLength;
var newBuffer = new ArrayBuffer(newLength);
new Uint8Array(newBuffer).set(new Uint8Array(oldBuffer));
return newBuffer;
}
// very tiny TextEncoder/TextDecoder polyfills that only supports utf-8 encoding
if (!TextEncoder) {
function TextEncoder (encoding) {}
TextEncoder.prototype.encode = function (buffer) {
buffer = unescape(encodeURIComponent(buffer));
var ab = new ArrayBuffer(buffer.length),
u8 = new Uint8Array(ab);
for (var i = 0; i < buffer.length; i ++)
u8[i] = buffer.charCodeAt(i);
return u8;
}
function TextDecoder () {}
TextDecoder.prototype.decode = function (buffer) {
return decodeURIComponent(escape(String.fromCharCode.apply(null, Array.from(buffer))));
}
}
var MetaView = (function () {
function MetaView (from) {
this.cursor = 0;
this.contents = new ArrayBuffer(1);
this.endianness = MetaView.LE;
if (from)
this.contents = ArrayBuffer.transfer(from);
// wraps some DataView methods
var types = {"Int": [8,16,32], "Uint": [8,16,32], "Float": [32,64]};
for (var type in types) {
for (var i = 0, size; i < types[type].length; i ++) {
size = types[type][i];
MetaView.prototype["write" + type + size] = MetaView.prototype.writeData.bind(this, type, size);
MetaView.prototype["read" + type + size] = MetaView.prototype.readData.bind(this, type, size);
}
}
}
MetaView.LE = true;
MetaView.BE = false;
MetaView.prototype = {
expandToContain: function (dataSize) {
var newLength = this.contents.byteLength;
while (this.cursor + dataSize > newLength)
newLength *= 2;
this.contents = ArrayBuffer.transfer(this.contents, newLength);
},
finalize: function () {
return this.contents = this.contents.slice(0, this.cursor);
},
writeData: function (type, bits, data) {
var bytes = bits / 8, dataLength = data.length || 1;
this.expandToContain(dataLength * bytes);
var dv = new DataView(this.contents);
for (var i = 0; i < dataLength; i ++) {
dv["set" + type + bits](this.cursor, data[i] || data, this.endianness);
this.cursor += bytes;
}
},
readData: function (type, bits, length) {
length = length || 1;
var dv = new DataView(this.contents);
var result = [];
while (length --) {
result.push(dv["get" + type + bits](this.cursor, this.endianness));
this.cursor += bits / 8;
}
return result.length == 1 ? result[0] : result;
},
writeUTF8String: function (string) {
var encoded = new TextEncoder("utf-8").encode(string);
this.writeUint32(encoded.byteLength);
this.writeUint8(encoded);
},
readUTF8String: function () {
var length = this.readUint32();
var encoded = this.readUint8(length);
return new TextDecoder("utf-8").decode(new Uint8Array(encoded));
}
};
return MetaView;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment