Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extensions to guid #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 119 additions & 7 deletions guid.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var validator = new RegExp("^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$", "i");
var hex_validator = new RegExp("^[a-z0-9]{32}$", "i");

function gen(count) {
var out = "";
Expand All @@ -8,21 +9,107 @@ function gen(count) {
return out;
}

var _bin2hex = [
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
];

var _hex2bin = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // 0-9
0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A-F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a-f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];

function bin2hex(str) {
var len = str.length;
var rv = '';
var i = 0;
var c;

while (len-- > 0) {
if(str instanceof Buffer)
c = str[i++];
else
c = str.charCodeAt(i++);

rv += _bin2hex[(c & 0xf0) >> 4];
rv += _bin2hex[(c & 0x0f)];
}
return rv;
}

function hex2bin(str) {
var len = str.length;
var rv = [];
var i = 0;

var c1;
var c2;

while (len > 1) {
h1 = str.charAt(i++);
c1 = h1.charCodeAt(0);
h2 = str.charAt(i++);
c2 = h2.charCodeAt(0);

rv.push((_hex2bin[c1] << 4) + _hex2bin[c2]);
len -= 2;
}

return rv;
}

function hex2uuid(hex) {
return hex.substr(0, 8) + "-" +
hex.substr(8, 4) + "-" +
hex.substr(12, 4) + "-" +
hex.substr(16, 4) + "-" +
hex.substr(20);
}


function Guid(guid) {
if (!guid) throw new TypeError("Invalid argument; `value` has no value.");

var value = Guid.EMPTY;
var bin = null;

if (guid && guid instanceof Guid) {
// Guid instances
value = Guid.toString();

} else if (guid && Object.prototype.toString.call(guid) === "[object String]" && Guid.isGuid(guid)) {
value = guid;
} else if (guid && guid instanceof Buffer) {
// binary buffer
value = hex2uuid(bin2hex(guid));
} else if (guid && Object.prototype.toString.call(guid) === "[object String]") {
if(Guid.isGuid(guid, true)) {
if(guid.length == 32) // value is a pure hex string
value = hex2uuid(guid)
else
value = guid;
} else if (guid.length == 16) {
value = hex2uuid(bin2hex(guid));
}
}

this.equals = function(other) {
// Comparing string `value` against provided `guid` will auto-call
// toString on `guid` for comparison
if (typeof(other) == 'string') {
return (other === this.toString());
}
return Guid.isGuid(other) && value == other;
};

Expand All @@ -37,22 +124,47 @@ function Guid(guid) {
this.toJSON = function() {
return value;
};

this.toHex = function() {
return value.split("-").join("")
}

this.toArray = function() {
return hex2bin(this.toHex())
}

this.toBytes = function() {
if(bin) return bin
return bin = new Buffer(this.toArray());
}

this.inspect = function() {
return "<Guid " + this.value + ">"
}

Object.defineProperty(this, "value", {
get: function() { return value; },
enumerable: true
});

Object.defineProperty(this, "bytes", {
get: function() { return this.toBytes(); },
enumerable: true
});
};

Object.defineProperty(Guid, "EMPTY", {
value: "00000000-0000-0000-0000-000000000000"
});

Guid.isGuid = function(value) {
return value && (value instanceof Guid || validator.test(value.toString()));
Guid.isGuid = function(value, loose) {
return value && (value instanceof Guid || validator.test(value.toString()) ||
loose && hex_validator.test(value.toString()));
};

Guid.create = function() {
Guid.create = function(value) {
if(value)
return new Guid(value);
return new Guid([gen(2), gen(1), gen(1), gen(1), gen(3)].join("-"));
};

Expand Down
47 changes: 47 additions & 0 deletions tests/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
var Guid = require('../guid');
var vows = require('vows'),
assert = require('assert');


module.exports = tests = {}


tests.suite1 = vows.describe('guid tests').addBatch({
"test1": {
"raw interface": function() {
var g = Guid.raw();
assert.ok(g);
assert.equal(typeof(g), 'string')
assert.equal(g.length, 36)
return
},

"object interface": function() {
var tar = [109, 210, 117, 221, 229, 152, 237, 212, 77, 119, 59, 248, 68, 107, 97, 183];

var g = Guid.create("6dd275dd-e598-edd4-4d77-3bf8446b61b7");
'm\xd2u\xdd\xe5\x98\xed\xd4Mw;\xf8Dka\xb7'
assert.ok(g.equals("6dd275dd-e598-edd4-4d77-3bf8446b61b7"), "not equal to string");

assert.equal(g.toHex(), '6dd275dde598edd44d773bf8446b61b7');
assert.equal(g.value, new Guid.create('6dd275dde598edd44d773bf8446b61b7').value);
assert.deepEqual(g.toArray(),
tar,
"array is not equal");

buf = g.toBytes();
assert.ok(buf instanceof Buffer, "buffer");
for(var i = 0; i < tar.length; i++)
assert.equal(buf[i], tar[i], "buffer differs");

var g2 = Guid.create(buf);
assert.equal(g.value, g2.value, "copy over buffer failed");

var g3 = Guid.create('\x00\x00\x00\x00\x00\x00\x00\x00\xab\xcd\x12\x34\x56\x78\x90\x12');
assert.equal(g3.value, "00000000-0000-0000-abcd-123456789012")

}
},
});

console.log(vows)