mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Preliminary binary-type commit
Note: Files will be moved around as much of the new type-handling stuff gets mvoved into a new ejson package. Testing to come
This commit is contained in:
committed by
David Glasser
parent
8ae6e71715
commit
950f1e0213
127
packages/livedata/base64.js
Normal file
127
packages/livedata/base64.js
Normal file
@@ -0,0 +1,127 @@
|
||||
// Base 64 encoding
|
||||
|
||||
(function () {
|
||||
|
||||
var BASE_64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
var BASE_64_VALS = {};
|
||||
|
||||
for (var i = 0; i < BASE_64_CHARS.length; i++) {
|
||||
BASE_64_VALS[BASE_64_CHARS.substr(i, 1)] = i;
|
||||
};
|
||||
|
||||
Meteor._base64Encode = function (array) {
|
||||
var answer = [];
|
||||
var a = null;
|
||||
var b = null;
|
||||
var c = null;
|
||||
var d = null;
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
switch (i % 3) {
|
||||
case 0:
|
||||
a = (array[i] >> 2) & 0x3F;
|
||||
b = (array[i] & 0x03) << 4;
|
||||
break;
|
||||
case 1:
|
||||
b = b | (array[i] >> 4) & 0xF;
|
||||
c = (array[i] & 0xF) << 2;
|
||||
break;
|
||||
case 2:
|
||||
c = c | (array[i] >> 6) & 0x03;
|
||||
d = array[i] & 0x3F;
|
||||
answer.push(getChar(a));
|
||||
answer.push(getChar(b));
|
||||
answer.push(getChar(c));
|
||||
answer.push(getChar(d));
|
||||
a = null;
|
||||
b = null;
|
||||
c = null;
|
||||
d = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (a != null) {
|
||||
answer.push(getChar(a));
|
||||
answer.push(getChar(b));
|
||||
if (c == null)
|
||||
answer.push('=');
|
||||
else
|
||||
answer.push(getChar(c));
|
||||
if (d == null)
|
||||
answer.push('=');
|
||||
}
|
||||
return answer.join("");
|
||||
};
|
||||
|
||||
var getChar = function (val) {
|
||||
return BASE_64_CHARS.substr(val, 1);
|
||||
};
|
||||
|
||||
var getVal = function (ch) {
|
||||
if (ch === '=') {
|
||||
return -1;
|
||||
}
|
||||
return BASE_64_VALS[ch];
|
||||
};
|
||||
|
||||
var newBuffer = function (len) {
|
||||
if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined') {
|
||||
var ret = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
ret.push(0);
|
||||
}
|
||||
ret.$Uint8ArrayPolyfill = true;
|
||||
return ret;
|
||||
}
|
||||
return new Uint8Array(new ArrayBuffer(len));
|
||||
};
|
||||
|
||||
Meteor._base64Decode = function (str) {
|
||||
var len = Math.floor((str.length*3)/4);
|
||||
if (str.substr(str.length - 1) == '=') {
|
||||
len--;
|
||||
if (str.substr(str.length - 2, 1) == '=')
|
||||
len--;
|
||||
}
|
||||
var arr = newBuffer(len);
|
||||
|
||||
var one = null;
|
||||
var two = null;
|
||||
var three = null;
|
||||
|
||||
var j = 0;
|
||||
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var c = str.substr(i, 1);
|
||||
var v = getVal(c);
|
||||
switch (i % 4) {
|
||||
case 0:
|
||||
if (v < 0)
|
||||
throw new Error('invalid base64 string');
|
||||
one = v << 2;
|
||||
break;
|
||||
case 1:
|
||||
if (v < 0)
|
||||
throw new Error('invalid base64 string');
|
||||
one = one | (v >> 4);
|
||||
arr[j++] = one;
|
||||
two = (v & 0x0F) << 4;
|
||||
break;
|
||||
case 2:
|
||||
if (v > 0) {
|
||||
two = two | (v >> 2);
|
||||
arr[j++] = two;
|
||||
three = (v & 0x03) << 6;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (v > 0) {
|
||||
arr[j++] = three | v;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -99,6 +99,21 @@ var builtinConverters = [
|
||||
return new Date(obj.$date);
|
||||
}
|
||||
},
|
||||
{ // Binary
|
||||
matchJSONValue: function (obj) {
|
||||
return _.has(obj, '$binary') && _.size(obj) === 1;
|
||||
},
|
||||
matchObject: function (obj) {
|
||||
return typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array
|
||||
|| (obj && _.has(obj, '$Uint8ArrayPolyfill'));
|
||||
},
|
||||
toJSONValue: function (obj) {
|
||||
return {$binary: Meteor._base64Encode(obj)};
|
||||
},
|
||||
fromJSONValue: function (obj) {
|
||||
return Meteor._base64Decode(obj.$binary);
|
||||
}
|
||||
},
|
||||
{ // Literal
|
||||
matchJSONValue: function (obj) {
|
||||
return _.has(obj, '$literal') && _.size(obj) === 1;
|
||||
|
||||
@@ -13,6 +13,7 @@ Package.on_use(function (api) {
|
||||
|
||||
api.add_files('writefence.js', 'server');
|
||||
api.add_files('crossbar.js', 'server');
|
||||
api.add_files('base64.js', ['client', 'server']);
|
||||
|
||||
api.add_files('livedata_common.js', ['client', 'server']);
|
||||
|
||||
@@ -35,4 +36,5 @@ Package.on_test(function (api) {
|
||||
api.add_files('livedata_tests.js', ['client', 'server']);
|
||||
api.add_files('livedata_test_service.js', ['client', 'server']);
|
||||
api.add_files('session_view_tests.js', ['server']);
|
||||
api.add_files('test_base64.js', ['client', 'server']);
|
||||
});
|
||||
|
||||
47
packages/livedata/test_base64.js
Normal file
47
packages/livedata/test_base64.js
Normal file
@@ -0,0 +1,47 @@
|
||||
(function () {
|
||||
|
||||
var asciiToArray = function (str) {
|
||||
var arr = new Uint8Array(new ArrayBuffer(str.length));
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var c = str.charCodeAt(i);
|
||||
if (c > 0xFF) {
|
||||
throw new Error("Not ascii");
|
||||
}
|
||||
arr[i] = c;
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
var arrayToAscii = function (arr) {
|
||||
var res = [];
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
res.push(String.fromCharCode(arr[i]));
|
||||
}
|
||||
return res.join("");
|
||||
};
|
||||
|
||||
Tinytest.add("base64 - testing the test", function (test) {
|
||||
test.equal(arrayToAscii(asciiToArray("The quick brown fox jumps over the lazy dog")),
|
||||
"The quick brown fox jumps over the lazy dog");
|
||||
});
|
||||
|
||||
Tinytest.add("base64 - empty", function (test) {
|
||||
test.equal(Meteor._base64Encode(new Uint8Array(new ArrayBuffer(0))), "");
|
||||
test.equal(Meteor._base64Decode(""), new Uint8Array(new ArrayBuffer(0)));
|
||||
});
|
||||
|
||||
|
||||
Tinytest.add("base64 - wikipedia examples", function (test) {
|
||||
var tests = [
|
||||
{txt: "pleasure.", res: "cGxlYXN1cmUu"},
|
||||
{txt: "leasure.", res: "bGVhc3VyZS4="},
|
||||
{txt: "easure.", res: "ZWFzdXJlLg=="},
|
||||
{txt: "asure.", res: "YXN1cmUu"},
|
||||
{txt: "sure.", res: "c3VyZS4="}
|
||||
];
|
||||
_.each(tests, function(t) {
|
||||
test.equal(Meteor._base64Encode(asciiToArray(t.txt)), t.res);
|
||||
test.equal(arrayToAscii(Meteor._base64Decode(t.res)), t.txt);
|
||||
});
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user