Skip to content

Instantly share code, notes, and snippets.

@endash
Last active August 29, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save endash/125e9713c97b7c72d305 to your computer and use it in GitHub Desktop.
Save endash/125e9713c97b7c72d305 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Struct</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.15.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="http://code.jquery.com/qunit/qunit-1.15.0.js"></script>
<script src="struct.js"></script>
<script src="struct-tests.js"></script>
</body>
</html>
"use strict";
test("Can define a struct with arguments or an array", function () {
var a, b;
ok(a = Struct("a", "b", "c"));
ok(b = Struct(["a", "b", "c"]));
equal(a.attrs.length, 3);
equal(b.attrs.length, 3);
});
test("Cannot define an empty struct", function () {
throws(function () { Struct(); });
throws(function () { Struct([]); });
});
test("Passed attributes must match the definition", function () {
var struct = Struct("a", "b", "c");
throws(function () { new struct(); });
throws(function () { new struct({a: 5}); });
throws(function () { new struct({a: 5, b: 8, c: 9, d: 8}); });
});
test("Struct is frozen", function () {
var struct = Struct("a", "b", "c");
var obj = new struct({a: 1, b: 2, c: 3});
throws(function () { obj.a = 5 });
});
test("Can read attributes from a struct", function () {
var StructA = Struct("a", "b", "c");
equal((new StructA({a: 1, b: 2, c: 3})).a, 1);
});
test("Anonymous struct toString", function () {
var StructA = Struct("a");
equal(StructA.toString(), "Struct<a>");
});
test("Anonymous struct instance toString", function () {
var StructA = Struct("a", "b");
var obj = new StructA({a: 1, b: 2});
equal(obj.toString(), "Struct<a=1,b=2>");
});
test("Named struct toString", function () {
var StructA = Struct("name").named("Person");
equal(StructA.toString(), "Person<name>");
});
window.Struct = (function () {
"use strict";
function arrayEquals(array1, array2) {
if (array1.length != array2.length) { return false; }
var i = 0, len = array1.length;
for (i; i < len; i++) {
if (array1[i] !== array2[i]) { return false; }
}
return true;
}
return function(attrNames) {
if (arguments.length == 0) throw "Cannot define an empty struct";
if (attrNames.constructor != Array) { attrNames = Array.prototype.slice.call(arguments); }
if (!attrNames.length) throw "Cannot define an empty struct";
var sortedAttrNames = attrNames.slice().sort();
var joinedAttrNames = sortedAttrNames.join(", ");
var attrsLength = attrNames.length;
var name = "Struct";
var func = function (attrs) {
if (arguments.length == 0 || attrs.constructor != Object) throw "Must pass a hash of attributes to a Struct";
var keys = Object.keys(attrs).sort();
if (!arrayEquals(keys, sortedAttrNames)) {
throw "Attributes (" + keys.join(", ") + ") do not match the struct factory definition (" + joinedAttrNames + ")";
}
var i = 0;
var attrName;
for (i; i < attrsLength; i++) {
attrName = attrNames[i];
this[attrName] = attrs[attrName];
}
Object.freeze(this);
}
func.named = function (newName) {
if (name != "Struct") throw "This Struct has already been named: '" + name + "'";
name = newName;
return this;
};
func.toString = function () { return name + "<" + joinedAttrNames + ">"; };
func.attrs = sortedAttrNames;
func.prototype = {
toString: function () {
var attrStrings = []
for (var i = 0, attr; i < sortedAttrNames.length; i++) {
attr = sortedAttrNames[i];
attrStrings.push(attr + "=" + this[attr]);
}
return name + "<" + attrStrings.join(",") + ">";
}
};
return func;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment