Demo JavaScript Compilation

April 2, 2017 ยท View on GitHub

// Code generated by colf(1); DO NOT EDIT. // The compiler used schema file demo.colf for package demo.

// Package demo offers a demonstration. // These comment lines will end up in the generated code. var demo = new function() { const EOF = 'colfer: EOF';

// The upper limit for serial byte sizes.
var colferSizeMax = 16 * 1024 * 1024;
// The upper limit for the number of elements in a list.
var colferListMax = 64 * 1024;

// Constructor.
// Course is the grounds where the game of golf is played.
// When init is provided all enumerable properties are merged into the new object a.k.a. shallow cloning.
this.Course = function(init) {

	this.ID = 0;

	this.name = '';

	this.holes = [];

	this.image = new Uint8Array(0);

	this.tags = [];

	for (var p in init) this[p] = init[p];
}

// Serializes the object into an Uint8Array.
// All null entries in property holes will be replaced with a new demo.Hole.
// All null entries in property tags will be replaced with an empty String.
this.Course.prototype.marshal = function() {
	var segs = [];

	if (this.ID) {
		if (this.ID < 0)
			throw 'colfer: demo/Course field ID out of reach: ' + this.ID;
		if (this.ID > Number.MAX_SAFE_INTEGER)
			throw 'colfer: demo/Course field ID exceeds Number.MAX_SAFE_INTEGER';
		if (this.ID < 0x2000000000000) {
			var seg = [0];
			encodeVarint(seg, this.ID);
			segs.push(seg);
		} else {
			var bytes = new Uint8Array(9);
			bytes[0] = 0 | 128;
			var view = new DataView(bytes.buffer);
			view.setUint32(1, this.ID / 0x100000000);
			view.setUint32(5, this.ID % 0x100000000);
			segs.push(bytes)
		}
	}

	if (this.name) {
		var utf = encodeUTF8(this.name);
		var seg = [1];
		encodeVarint(seg, utf.length);
		segs.push(seg);
		segs.push(utf)
	}

	if (this.holes && this.holes.length) {
		var a = this.holes;
		if (a.length > colferListMax)
			throw 'colfer: demo.course.holes length exceeds colferListMax';
		var seg = [2];
		encodeVarint(seg, a.length);
		segs.push(seg);
		for (var i = 0; i < a.length; i++) {
			var v = a[i];
			if (v == null) {
				v = new demo.Hole();
				a[i] = v;
			}
			segs.push(v.marshal());
		};
	}

	if (this.image && this.image.length) {
		var seg = [3];
		encodeVarint(seg, this.image.length);
		segs.push(seg);
		segs.push(this.image);
	}

	if (this.tags && this.tags.length) {
		var a = this.tags;
		if (a.length > colferListMax)
			throw 'colfer: demo.course.tags length exceeds colferListMax';
		var seg = [4];
		encodeVarint(seg, a.length);
		segs.push(seg);
		for (var i = 0; i < a.length; i++) {
			var s = a[i];
			if (s == null) {
				s = "";
				a[i] = s;
			}
			var utf = encodeUTF8(s);
			seg = [];
			encodeVarint(seg, utf.length);
			segs.push(seg);
			segs.push(utf)
		}
	}

	var size = 1;
	segs.forEach(function(seg) {
		size += seg.length;
	});
	if (size > colferSizeMax)
		throw 'colfer: demo.course serial size ' + size + ' exceeds ' + colferListMax + ' bytes';

	var bytes = new Uint8Array(size);
	var i = 0;
	segs.forEach(function(seg) {
		bytes.set(seg, i);
		i += seg.length;
	});
	bytes[i] = 127;
	return bytes;
}

// Deserializes the object from an Uint8Array and returns the number of bytes read.
this.Course.prototype.unmarshal = function(data) {
	if (!data || ! data.length) throw EOF;
	var header = data[0];
	var i = 1;
	var readHeader = function() {
		if (i >= data.length) throw EOF;
		header = data[i++];
	}

	var readVarint = function() {
		var pos = 0, result = 0;
		while (pos != 8) {
			var c = data[i+pos];
			result += (c & 127) * Math.pow(128, pos);
			++pos;
			if (c < 128) {
				i += pos;
				if (result > Number.MAX_SAFE_INTEGER) break;
				return result;
			}
			if (pos == data.length) throw EOF;
		}
		return -1;
	}

	if (header == 0) {
		var x = readVarint();
		if (x < 0) throw 'colfer: demo/Course field ID exceeds Number.MAX_SAFE_INTEGER';
		this.ID = x;
		readHeader();
	} else if (header == (0 | 128)) {
		if (i + 8 > data.length) throw EOF;
		var view = new DataView(data.buffer);
		var x = view.getUint32(i) * 0x100000000;
		x += view.getUint32(i + 4);
		if (x > Number.MAX_SAFE_INTEGER)
			throw 'colfer: demo/Course field ID exceeds Number.MAX_SAFE_INTEGER';
		this.ID = x;
		i += 8;
		readHeader();
	}

	if (header == 1) {
		var size = readVarint();
		if (size < 0)
			throw 'colfer: demo.course.name size exceeds Number.MAX_SAFE_INTEGER';
		else if (size > colferSizeMax)
			throw 'colfer: demo.course.name size ' + size + ' exceeds ' + colferSizeMax + ' UTF-8 bytes';
		var to = i + size;
		if (to > data.length) throw EOF;
		this.name = decodeUTF8(data.subarray(i, to));
		i = to;
		readHeader();
	}

	if (header == 2) {
		var length = readVarint();
		if (length < 0)
			throw 'colfer: demo.course.holes length exceeds Number.MAX_SAFE_INTEGER';
		if (length > colferListMax)
			throw 'colfer: demo.course.holes length ' + length + ' exceeds ' + colferListMax + ' elements';
		while (--length >= 0) {
			var o = new demo.Hole();
			i += o.unmarshal(data.subarray(i));
			this.holes.push(o);
		}
		readHeader();
	}

	if (header == 3) {
		var size = readVarint();
		if (size < 0)
			throw 'colfer: demo.course.image size exceeds Number.MAX_SAFE_INTEGER';
		else if (size > colferSizeMax)
			throw 'colfer: demo.course.image size ' + size + ' exceeds ' + colferSizeMax + ' bytes';
		var to = i + size;
		if (to > data.length) throw EOF;
		this.image = data.subarray(i, to);
		i = to;
		readHeader();
	}

	if (header == 4) {
		var length = readVarint();
		if (length < 0)
			throw 'colfer: demo.course.tags length exceeds Number.MAX_SAFE_INTEGER';
		if (length > colferListMax)
			throw 'colfer: demo.course.tags length ' + length + ' exceeds ' + colferListMax + ' elements';
		while (--length >= 0) {
			var size = readVarint();
			if (size < 0)
				throw 'colfer: demo.course.tags element ' + this.tags.length + ' size exceeds Number.MAX_SAFE_INTEGER';
			else if (size > colferSizeMax)
				throw 'colfer: demo.course.tags element ' + this.tags.length + ' size ' + size + ' exceeds ' + colferSizeMax + ' UTF-8 bytes';
			var to = i + size;
			if (to > data.length) throw EOF;
			this.tags.push(decodeUTF8(data.subarray(i, to)));
			i = to;
		}
		readHeader();
	}

	if (header != 127) throw 'colfer: unknown header at byte ' + (i - 1);
	if (i > colferSizeMax)
		throw 'colfer: demo.course serial size ' + size + ' exceeds ' + colferSizeMax + ' bytes';
	return i;
}

// Constructor.

// When init is provided all enumerable properties are merged into the new object a.k.a. shallow cloning.
this.Hole = function(init) {
	// Lat is the latitude of the cup.
	this.lat = 0;
	// Lon is the longitude of the cup.
	this.lon = 0;
	// Par is the difficulty index.
	this.par = 0;
	// Water marks the presence of water.
	this.water = false;
	// Sand marks the presence of sand.
	this.sand = false;

	for (var p in init) this[p] = init[p];
}

// Serializes the object into an Uint8Array.
this.Hole.prototype.marshal = function() {
	var segs = [];

	if (this.lat || Number.isNaN(this.lat)) {
		var bytes = new Uint8Array(9);
		bytes[0] = 0;
		new DataView(bytes.buffer).setFloat64(1, this.lat);
		segs.push(bytes);
	}

	if (this.lon || Number.isNaN(this.lon)) {
		var bytes = new Uint8Array(9);
		bytes[0] = 1;
		new DataView(bytes.buffer).setFloat64(1, this.lon);
		segs.push(bytes);
	}

	if (this.par) {
		if (this.par > 255 || this.par < 0)
			throw 'colfer: demo/Hole field par out of reach: ' + this.par;
		segs.push([2, this.par]);
	}

	if (this.water)
		segs.push([3]);

	if (this.sand)
		segs.push([4]);

	var size = 1;
	segs.forEach(function(seg) {
		size += seg.length;
	});
	if (size > colferSizeMax)
		throw 'colfer: demo.hole serial size ' + size + ' exceeds ' + colferListMax + ' bytes';

	var bytes = new Uint8Array(size);
	var i = 0;
	segs.forEach(function(seg) {
		bytes.set(seg, i);
		i += seg.length;
	});
	bytes[i] = 127;
	return bytes;
}

// Deserializes the object from an Uint8Array and returns the number of bytes read.
this.Hole.prototype.unmarshal = function(data) {
	if (!data || ! data.length) throw EOF;
	var header = data[0];
	var i = 1;
	var readHeader = function() {
		if (i >= data.length) throw EOF;
		header = data[i++];
	}

	var readVarint = function() {
		var pos = 0, result = 0;
		while (pos != 8) {
			var c = data[i+pos];
			result += (c & 127) * Math.pow(128, pos);
			++pos;
			if (c < 128) {
				i += pos;
				if (result > Number.MAX_SAFE_INTEGER) break;
				return result;
			}
			if (pos == data.length) throw EOF;
		}
		return -1;
	}

	if (header == 0) {
		if (i + 8 > data.length) throw EOF;
		this.lat = new DataView(data.buffer).getFloat64(i);
		i += 8;
		readHeader();
	}

	if (header == 1) {
		if (i + 8 > data.length) throw EOF;
		this.lon = new DataView(data.buffer).getFloat64(i);
		i += 8;
		readHeader();
	}

	if (header == 2) {
		if (i + 1 >= data.length) throw EOF;
		this.par = data[i++];
		header = data[i++];
	}

	if (header == 3) {
		this.water = true;
		readHeader();
	}

	if (header == 4) {
		this.sand = true;
		readHeader();
	}

	if (header != 127) throw 'colfer: unknown header at byte ' + (i - 1);
	if (i > colferSizeMax)
		throw 'colfer: demo.hole serial size ' + size + ' exceeds ' + colferSizeMax + ' bytes';
	return i;
}

// private section

var encodeVarint = function(bytes, x) {
	while (x > 127) {
		bytes.push(x|128);
		x /= 128;
	}
	bytes.push(x&127);
	return bytes;
}

var encodeUTF8 = function(s) {
	var i = 0;
	var bytes = new Uint8Array(s.length * 4);
	for (var ci = 0; ci != s.length; ci++) {
		var c = s.charCodeAt(ci);
		if (c < 128) {
			bytes[i++] = c;
			continue;
		}
		if (c < 2048) {
			bytes[i++] = c >> 6 | 192;
		} else {
			if (c > 0xd7ff && c < 0xdc00) {
				if (++ci == s.length) throw 'UTF-8 encode: incomplete surrogate pair';
				var c2 = s.charCodeAt(ci);
				if (c2 < 0xdc00 || c2 > 0xdfff) throw 'UTF-8 encode: second char code 0x' + c2.toString(16) + ' at index ' + ci + ' in surrogate pair out of range';
				c = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
				bytes[i++] = c >> 18 | 240;
				bytes[i++] = c>> 12 & 63 | 128;
			} else { // c <= 0xffff
				bytes[i++] = c >> 12 | 224;
			}
			bytes[i++] = c >> 6 & 63 | 128;
		}
		bytes[i++] = c & 63 | 128;
	}
	return bytes.subarray(0, i);
}

var decodeUTF8 = function(bytes) {
	var s = '';
	var i = 0;
	while (i < bytes.length) {
		var c = bytes[i++];
		if (c > 127) {
			if (c > 191 && c < 224) {
				if (i >= bytes.length) throw 'UTF-8 decode: incomplete 2-byte sequence';
				c = (c & 31) << 6 | bytes[i] & 63;
			} else if (c > 223 && c < 240) {
				if (i + 1 >= bytes.length) throw 'UTF-8 decode: incomplete 3-byte sequence';
				c = (c & 15) << 12 | (bytes[i] & 63) << 6 | bytes[++i] & 63;
			} else if (c > 239 && c < 248) {
				if (i+2 >= bytes.length) throw 'UTF-8 decode: incomplete 4-byte sequence';
				c = (c & 7) << 18 | (bytes[i] & 63) << 12 | (bytes[++i] & 63) << 6 | bytes[++i] & 63;
			} else throw 'UTF-8 decode: unknown multibyte start 0x' + c.toString(16) + ' at index ' + (i - 1);
			++i;
		}

		if (c <= 0xffff) s += String.fromCharCode(c);
		else if (c <= 0x10ffff) {
			c -= 0x10000;
			s += String.fromCharCode(c >> 10 | 0xd800)
			s += String.fromCharCode(c & 0x3FF | 0xdc00)
		} else throw 'UTF-8 decode: code point 0x' + c.toString(16) + ' exceeds UTF-16 reach';
	}
	return s;
}

}

// NodeJS: if (typeof exports !== 'undefined') exports.demo = demo;