Skip to content

Create algorithm for converting base64 to binary data #757

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

Merged
merged 1 commit into from
Oct 8, 2021
Merged
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
47 changes: 47 additions & 0 deletions Conversions/Base64ToArrayBuffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// About base64: https://en.wikipedia.org/wiki/Base64

/**
* Converts a base64 string to an array of bytes
* @param {string} b64 A base64 string
* @returns {ArrayBuffer} An ArrayBuffer representing the bytes encoded by the base64 string
*/
function base64ToBuffer (b64) {
// The base64 encoding uses the following set of characters to encode any binary data as text
const base64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
// Find the index of char '=' first occurrence
const paddingIdx = b64.indexOf('=')
// Remove padding chars from base64 string, if there are any
const b64NoPadding = paddingIdx !== -1 ? b64.slice(0, paddingIdx) : b64
// Calculate the length of the result buffer
const bufferLength = Math.floor((b64NoPadding.length * 6) / 8)
// Create the result buffer
const result = new ArrayBuffer(bufferLength)
// Create an instance of Uint8Array, to write to the `result` buffer
const byteView = new Uint8Array(result)

// Loop through all chars in the base64 string, in increments of 4 chars, and in increments of 3 bytes
for (let i = 0, j = 0; i < b64NoPadding.length; i += 4, j += 3) {
// Get the index of the next 4 base64 chars
const b64Char1 = base64Table.indexOf(b64NoPadding[i])
const b64Char2 = base64Table.indexOf(b64NoPadding[i + 1])
let b64Char3 = base64Table.indexOf(b64NoPadding[i + 2])
let b64Char4 = base64Table.indexOf(b64NoPadding[i + 3])

// If base64 chars 3 and 4 don't exit, then set them to 0
if (b64Char3 === -1) b64Char3 = 0
if (b64Char4 === -1) b64Char4 = 0

// Calculate the next 3 bytes
const byte1 = (b64Char1 << 2) + ((b64Char2 & 48) >> 4)
const byte2 = ((b64Char2 & 15) << 4) + ((b64Char3 & 60) >> 2)
const byte3 = ((b64Char3 & 3) << 6) + b64Char4

byteView[j] = byte1
byteView[j + 1] = byte2
byteView[j + 2] = byte3
}

return result
}

export { base64ToBuffer }
26 changes: 26 additions & 0 deletions Conversions/test/Base64ToArrayBuffer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { base64ToBuffer } from '../Base64ToArrayBuffer'
import { TextDecoder } from 'util'

describe('Base64ToArrayBuffer', () => {
it('should decode "SGVsbG8sIHdvcmxkIQ==" as "Hello, world!"', () => {
const testBase64String = 'SGVsbG8sIHdvcmxkIQ=='
const buffer = base64ToBuffer(testBase64String)
const decoder = new TextDecoder()
const helloWorldString = decoder.decode(buffer)
expect(helloWorldString).toBe('Hello, world!')
})

it('should decode base64 "Nxex6kQaWg==" as binary buffer [55,23,177,234,68,26,90]', () => {
const testBase64String = 'Nxex6kQaWg=='
const buffer = base64ToBuffer(testBase64String)
const array = [...new Uint8Array(buffer)]
expect(array).toEqual([55, 23, 177, 234, 68, 26, 90])
})

it('should decode base64 "AAECAwQFBgcICQ==" as binary buffer [0,1,2,3,4,5,6,7,8,9]', () => {
const testBase64String = 'AAECAwQFBgcICQ=='
const buffer = base64ToBuffer(testBase64String)
const array = [...new Uint8Array(buffer)]
expect(array).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
})
})