Skip to content

Commit 0170684

Browse files
authored
chore: Merge pull request #757 from nibble-4bits/algorithm/base64ToBuffer
Create algorithm for converting base64 to binary data
2 parents 2ae093b + d6193f6 commit 0170684

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

Conversions/Base64ToArrayBuffer.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// About base64: https://en.wikipedia.org/wiki/Base64
2+
3+
/**
4+
* Converts a base64 string to an array of bytes
5+
* @param {string} b64 A base64 string
6+
* @returns {ArrayBuffer} An ArrayBuffer representing the bytes encoded by the base64 string
7+
*/
8+
function base64ToBuffer (b64) {
9+
// The base64 encoding uses the following set of characters to encode any binary data as text
10+
const base64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
11+
// Find the index of char '=' first occurrence
12+
const paddingIdx = b64.indexOf('=')
13+
// Remove padding chars from base64 string, if there are any
14+
const b64NoPadding = paddingIdx !== -1 ? b64.slice(0, paddingIdx) : b64
15+
// Calculate the length of the result buffer
16+
const bufferLength = Math.floor((b64NoPadding.length * 6) / 8)
17+
// Create the result buffer
18+
const result = new ArrayBuffer(bufferLength)
19+
// Create an instance of Uint8Array, to write to the `result` buffer
20+
const byteView = new Uint8Array(result)
21+
22+
// Loop through all chars in the base64 string, in increments of 4 chars, and in increments of 3 bytes
23+
for (let i = 0, j = 0; i < b64NoPadding.length; i += 4, j += 3) {
24+
// Get the index of the next 4 base64 chars
25+
const b64Char1 = base64Table.indexOf(b64NoPadding[i])
26+
const b64Char2 = base64Table.indexOf(b64NoPadding[i + 1])
27+
let b64Char3 = base64Table.indexOf(b64NoPadding[i + 2])
28+
let b64Char4 = base64Table.indexOf(b64NoPadding[i + 3])
29+
30+
// If base64 chars 3 and 4 don't exit, then set them to 0
31+
if (b64Char3 === -1) b64Char3 = 0
32+
if (b64Char4 === -1) b64Char4 = 0
33+
34+
// Calculate the next 3 bytes
35+
const byte1 = (b64Char1 << 2) + ((b64Char2 & 48) >> 4)
36+
const byte2 = ((b64Char2 & 15) << 4) + ((b64Char3 & 60) >> 2)
37+
const byte3 = ((b64Char3 & 3) << 6) + b64Char4
38+
39+
byteView[j] = byte1
40+
byteView[j + 1] = byte2
41+
byteView[j + 2] = byte3
42+
}
43+
44+
return result
45+
}
46+
47+
export { base64ToBuffer }
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { base64ToBuffer } from '../Base64ToArrayBuffer'
2+
import { TextDecoder } from 'util'
3+
4+
describe('Base64ToArrayBuffer', () => {
5+
it('should decode "SGVsbG8sIHdvcmxkIQ==" as "Hello, world!"', () => {
6+
const testBase64String = 'SGVsbG8sIHdvcmxkIQ=='
7+
const buffer = base64ToBuffer(testBase64String)
8+
const decoder = new TextDecoder()
9+
const helloWorldString = decoder.decode(buffer)
10+
expect(helloWorldString).toBe('Hello, world!')
11+
})
12+
13+
it('should decode base64 "Nxex6kQaWg==" as binary buffer [55,23,177,234,68,26,90]', () => {
14+
const testBase64String = 'Nxex6kQaWg=='
15+
const buffer = base64ToBuffer(testBase64String)
16+
const array = [...new Uint8Array(buffer)]
17+
expect(array).toEqual([55, 23, 177, 234, 68, 26, 90])
18+
})
19+
20+
it('should decode base64 "AAECAwQFBgcICQ==" as binary buffer [0,1,2,3,4,5,6,7,8,9]', () => {
21+
const testBase64String = 'AAECAwQFBgcICQ=='
22+
const buffer = base64ToBuffer(testBase64String)
23+
const array = [...new Uint8Array(buffer)]
24+
expect(array).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
25+
})
26+
})

0 commit comments

Comments
 (0)