Skip to content

Commit

Permalink
feat: support ascii encoding (#2)
Browse files Browse the repository at this point in the history
For better or for worse, sometimes you want to covert between a Uint8Array and a string where each character of the string is created from the character code of the corresponding byte from the array.

Adds an `ascii` encoding which is similar to `binary` as used by node buffers.

It's not called `binary` as people confuse this with `base2`.
  • Loading branch information
achingbrain committed Aug 7, 2020
1 parent 5ccfa4d commit 098724d
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const fromString = require('uint8arrays/from-string')
console.info(fromString('hello world')) // Uint8Array[104, 101 ...
console.info(fromString('00010203aabbcc', 'base16')) // Uint8Array[0, 1 ...
console.info(fromString('AAECA6q7zA', 'base64')) // Uint8Array[0, 1 ...
console.info(fromString('01234', 'ascii')) // Uint8Array[48, 49 ...
```

### toString(array, encoding = 'utf8')
Expand All @@ -109,4 +110,5 @@ const fromString = require('uint8arrays/from-string')
console.info(toString(Uint8Array.from([104, 101...]))) // 'hello world'
console.info(toString(Uint8Array.from([0, 1, 2...]), 'base16')) // '00010203aabbcc'
console.info(toString(Uint8Array.from([0, 1, 2...]), 'base64')) // 'AAECA6q7zA'
console.info(toString(Uint8Array.from([48, 49, 50...]), 'ascii')) // '01234'
```
25 changes: 25 additions & 0 deletions from-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,30 @@ const { names } = require('multibase/src/constants')
const { TextEncoder } = require('web-encoding')
const utf8Encoder = new TextEncoder()

/**
* Interperets each character in a string as a byte and
* returns a Uint8Array of those bytes.
*
* @param {String} string The string to turn into an array
* @returns {Uint8Array}
*/
function asciiStringToUint8Array (string) {
const array = new Uint8Array(string.length)

for (let i = 0; i < string.length; i++) {
array[i] = string.charCodeAt(i)
}

return array
}

/**
* Create a `Uint8Array` from the passed string
*
* Supports `utf8`, `utf-8` and any encoding supported by the multibase module.
*
* Also `ascii` which is similar to node's 'binary' encoding.
*
* @param {String} string
* @param {String} [encoding=utf8] utf8, base16, base64, base64urlpad, etc
* @returns {Uint8Array}
Expand All @@ -17,6 +38,10 @@ function fromString (string, encoding = 'utf8') {
return utf8Encoder.encode(string)
}

if (encoding === 'ascii') {
return asciiStringToUint8Array(string)
}

const codec = names[encoding]

if (!codec) {
Expand Down
13 changes: 13 additions & 0 deletions test/from-string.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ describe('Uint8Array fromString', () => {
expect(fromString(str, 'base64')).to.deep.equal(arr)
})

it('creates a Uint8Array from an ascii string', () => {
const str = [
String.fromCharCode(0),
String.fromCharCode(1),
String.fromCharCode(2),
String.fromCharCode(3),
String.fromCharCode(4)
].join('')
const arr = Uint8Array.from([0, 1, 2, 3, 4])

expect(fromString(str, 'ascii')).to.deep.equal(arr)
})

it('throws when an unknown base is passed', () => {
const str = 'hello world'

Expand Down
13 changes: 13 additions & 0 deletions test/to-string.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ describe('Uint8Array toString', () => {
expect(toString(arr, 'base64')).to.deep.equal(str)
})

it('creates an ascii string from a Uint8Array', () => {
const str = [
String.fromCharCode(0),
String.fromCharCode(1),
String.fromCharCode(2),
String.fromCharCode(3),
String.fromCharCode(4)
].join('')
const arr = Uint8Array.from([0, 1, 2, 3, 4])

expect(toString(arr, 'ascii')).to.deep.equal(str)
})

it('throws when an unknown base is passed', () => {
const arr = Uint8Array.from([0, 1, 2, 3, 170, 187, 204])

Expand Down
32 changes: 27 additions & 5 deletions to-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,41 @@ const { names } = require('multibase/src/constants')
const { TextDecoder } = require('web-encoding')
const utf8Decoder = new TextDecoder('utf8')

/**
* Turns a Uint8Array of bytes into a string with each
* character being the char code of the corresponding byte
*
* @param {Uint8Array} array The array to turn into a string
* @returns {String}
*/
function uint8ArrayToAsciiString (array) {
let string = ''

for (let i = 0; i < array.length; i++) {
string += String.fromCharCode(array[i])
}
return string
}

/**
* Turns a `Uint8Array` into a string.
*
* Supports `utf8` and any encoding supported by the multibase module
* Supports `utf8`, `utf-8` and any encoding supported by the multibase module.
*
* Also `ascii` which is similar to node's 'binary' encoding.
*
* @param {Uint8Array} buf The array to turn into a string
* @param {Uint8Array} array The array to turn into a string
* @param {String} [encoding=utf8] The encoding to use
* @returns {String}
* @see {@link https://www.npmjs.com/package/multibase|multibase} for supported encodings other than `utf8`
*/
function toString (buf, encoding = 'utf8') {
function toString (array, encoding = 'utf8') {
if (encoding === 'utf8' || encoding === 'utf-8') {
return utf8Decoder.decode(buf)
return utf8Decoder.decode(array)
}

if (encoding === 'ascii') {
return uint8ArrayToAsciiString(array)
}

const codec = names[encoding]
Expand All @@ -25,7 +47,7 @@ function toString (buf, encoding = 'utf8') {
throw new Error('Unknown base')
}

return codec.encode(buf)
return codec.encode(array)
}

module.exports = toString

0 comments on commit 098724d

Please sign in to comment.