-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ab8de17
commit e34c0e7
Showing
3 changed files
with
125 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
namespace Base64 { | ||
const PADCHAR: string = '=' | ||
const ALPHA: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | ||
|
||
export function decodeBuffer(s: string): Uint8Array { | ||
let size: number = s.length | ||
|
||
if (size === 0) { | ||
return new Uint8Array(0) | ||
} | ||
if (size % 4 !== 0) { | ||
throw `Bad string length: ${size}` | ||
} | ||
for (let c of s) { | ||
if (ALPHA.indexOf(c) < 0 && c != PADCHAR) { | ||
throw `Invalid string encoding character: ${c}.` | ||
} | ||
} | ||
/** | ||
* Every four base64 characters = 24 bits = 3 bytes. | ||
* But, we also need to figure out padding, if any. | ||
*/ | ||
let bytes: number = 3 * size / 4 | ||
let numPad: number = 0 | ||
if (s.charAt(size - 1) === '=') { | ||
numPad++ | ||
bytes-- | ||
} | ||
if (s.charAt(size - 2) === '=') { | ||
numPad++ | ||
bytes-- | ||
} | ||
const buffer: Uint8Array = new Uint8Array(bytes) | ||
let index: number = 0, | ||
bufferIndex: number = 0, | ||
quantum: number | ||
if (numPad > 0) { | ||
size -= 4 // Handle the last one specially. | ||
} | ||
while (index < size) { | ||
quantum = 0 | ||
for (let i: number = 0; i < 4; ++i) { | ||
quantum = (quantum << 6) | | ||
ALPHA.indexOf(s.charAt(index + i)) | ||
} | ||
buffer.set(bufferIndex++, (quantum >> 16) & 0xff) | ||
buffer.set(bufferIndex++, (quantum >> 8) & 0xff) | ||
buffer.set(bufferIndex++, quantum & 0xff) | ||
index += 4 | ||
} | ||
if (numPad > 0) { | ||
/** | ||
* If numPad == 1, then there is one =, and we have 18 bits with 2 zeroes at the end. | ||
* If numPad == 2, then there are two =, and we have 12 bits with 4 zeroes at the end. | ||
* First, grab the quantum. | ||
*/ | ||
quantum = 0 | ||
for (let i: number = 0; i < 4 - numPad; ++i) { | ||
quantum = (quantum << 6) | | ||
ALPHA.indexOf(s.charAt(index + i)) | ||
} | ||
if (numPad === 1) { | ||
// quantum is 18 bits, but really represents two bytes. | ||
quantum = quantum >> 2 | ||
buffer.set(bufferIndex++, (quantum >> 8) & 0xff) | ||
buffer.set(bufferIndex++, quantum & 0xff) | ||
} else { | ||
// quantum is 12 bits, but really represents only one byte. | ||
quantum = quantum >> 4 | ||
buffer.set(bufferIndex++, quantum & 0xff) | ||
} | ||
} | ||
|
||
return buffer | ||
} | ||
|
||
export function encodeBuffer(bytes: ArrayBuffer): string { | ||
const array: Uint8Array = new Uint8Array(0) | ||
array.fromArrayBuffer(bytes) | ||
const base64: string[] = [] | ||
let index: number = 0, | ||
quantum: number, | ||
value: number | ||
// Grab as many sets of 3 bytes as we can, which form 24 bits. | ||
while (index + 2 < array.byteLength) { | ||
quantum = (array.get(index) << 16) | | ||
(array.get(index + 1) << 8) | | ||
array.get(index + 2) | ||
value = (quantum >> 18) & 0x3f | ||
base64.push(ALPHA[value]) | ||
value = (quantum >> 12) & 0x3f | ||
base64.push(ALPHA[value]) | ||
value = (quantum >> 6) & 0x3f | ||
base64.push(ALPHA[value]) | ||
value = quantum & 0x3f | ||
base64.push(ALPHA[value]) | ||
index += 3 | ||
} | ||
|
||
// At this point, there are 0, 1, or 2 bytes left. | ||
if (index + 1 === array.byteLength) { | ||
// 8 bits; shift by 4 to pad on the right with 0s to make 12 bits total. | ||
quantum = array.get(index) << 4 | ||
value = (quantum >> 6) & 0x3f | ||
base64.push(ALPHA[value]) | ||
value = quantum & 0x3f | ||
base64.push(ALPHA[value]) | ||
base64.push('==') | ||
} else if (index + 2 === array.byteLength) { | ||
// 16 bits; shift by 2 to pad on the right with 0s to make 18 bits total. | ||
quantum = (array.get(index) << 10) | | ||
(array.get(index + 1) << 2) | ||
value = (quantum >> 12) & 0x3f | ||
base64.push(ALPHA[value]) | ||
value = (quantum >> 6) & 0x3f | ||
base64.push(ALPHA[value]) | ||
value = quantum & 0x3f | ||
base64.push(ALPHA[value]) | ||
base64.push('=') | ||
} | ||
return base64.join('') | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +0,0 @@ | ||
let allPassed: boolean = true | ||
|
||
function areEquivalent(a: number[], b: ArrayBuffer): boolean { | ||
if (a.length != b.byteLength) { | ||
return false | ||
} | ||
for (let i: number = 0; i < a.length; i++) { | ||
if (a[i] != b.bytes[i]) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
function create(bytes: number[]): ArrayBuffer { | ||
let buffer: ArrayBuffer = new ArrayBuffer(bytes.length) | ||
let array: Uint8Array = new Uint8Array() | ||
array.fromArrayBuffer(buffer) | ||
|
||
for (let i: number = 0; i < bytes.length; i++) { | ||
array.set(i, bytes[i]) | ||
} | ||
|
||
return buffer | ||
} | ||
|
||
let buf: ArrayBuffer = create([0, 1, 2, 3, 4, 5, 6, 7, 8, 9,]) | ||
if (buf.byteLength != 10) { | ||
game.splash("Array buffer slice test 1 failed.") | ||
allPassed = false | ||
} | ||
if (buf.slice(5).byteLength != 5) { | ||
game.splash("Array buffer slice test 2 failed.") | ||
allPassed = false | ||
} | ||
if (buf.slice(-2).byteLength != 2) { | ||
game.splash("Array buffer slice test 3 failed.") | ||
allPassed = false | ||
} | ||
if (buf.slice(-4, -2).byteLength != 2) { | ||
game.splash("Array buffer slice test 4 failed.") | ||
allPassed = false | ||
} | ||
if (buf.slice(-1000, 5).byteLength != 5) { | ||
game.splash("Array buffer slice test 5 failed.") | ||
allPassed = false | ||
} | ||
if (!areEquivalent([5, 6, 7, 8, 9,], buf.slice(5))) { | ||
game.splash("Array buffer slice test 6 failed.") | ||
allPassed = false | ||
} | ||
if (!areEquivalent([0, 1, 2, 3, 4,], buf.slice(0, 5))) { | ||
game.splash("Array buffer slice test 7 failed.") | ||
allPassed = false | ||
} | ||
if (!areEquivalent([5, 6,], buf.slice(5, 7))) { | ||
game.splash("Array buffer slice test 8 failed.") | ||
allPassed = false | ||
} | ||
if (!areEquivalent([6, 7,], buf.slice(-4, -2))) { | ||
game.splash("Array buffer slice test 9 failed.") | ||
allPassed = false | ||
} | ||
if (!areEquivalent([2, 3, 4, 5, 6, 7,], buf.slice(2, -2))) { | ||
game.splash("Array buffer slice test 10 failed.") | ||
allPassed = false | ||
} | ||
|
||
if (allPassed) { | ||
game.splash("All tests passed!") | ||
} else { | ||
game.splash("At least one test failed.") | ||
} | ||