116 lines
3.3 KiB
JavaScript
116 lines
3.3 KiB
JavaScript
|
|
import test from 'fresh-tape'
|
||
|
|
import { encodingLength, encode, decode } from './index.mjs'
|
||
|
|
import * as utf8Codec from './index.mjs'
|
||
|
|
import { Buffer } from 'buffer'
|
||
|
|
|
||
|
|
function toHex (uint8) {
|
||
|
|
return Buffer.from(uint8).toString('hex')
|
||
|
|
}
|
||
|
|
|
||
|
|
const TEST_STRINGS = [
|
||
|
|
'', // empty
|
||
|
|
'basic: hi',
|
||
|
|
'japanese: 日本語',
|
||
|
|
'mixed: 日本語 hi',
|
||
|
|
'min 1 byte: \x00',
|
||
|
|
'odd 1 byte: \x4c',
|
||
|
|
'max 1 byte: \x7f',
|
||
|
|
'min 2 byte: \x80',
|
||
|
|
'odd 2 byte: \xd941',
|
||
|
|
'max 2 byte: \x7fff',
|
||
|
|
'min 3 byte: \x8000',
|
||
|
|
'odd 3 byte: \xa158',
|
||
|
|
'max 3 byte: \xffff',
|
||
|
|
`4 byte: ${String.fromCodePoint(100000)}`
|
||
|
|
]
|
||
|
|
TEST_STRINGS.forEach((fixture, index) => {
|
||
|
|
test(`fixture #${index}`, t => {
|
||
|
|
const check = Buffer.from(fixture)
|
||
|
|
const len = check.length
|
||
|
|
t.equals(encodingLength(fixture), len, `fixture ${fixture} length`)
|
||
|
|
const buf = new Uint8Array(len)
|
||
|
|
t.equals(toHex(encode(fixture, buf, 0), 0, len), check.toString('hex'), `write: ${fixture}`)
|
||
|
|
t.equals(encode.bytes, len, 'write.num')
|
||
|
|
t.equals(decode(check), check.toString(), `toUtf8: ${fixture}`)
|
||
|
|
t.equals(decode.bytes, check.length, 'write.num')
|
||
|
|
t.end()
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
test('surrogate pairs', function (t) {
|
||
|
|
[
|
||
|
|
[0xd821, 0xdea0],
|
||
|
|
[0xd800, 0xdc00],
|
||
|
|
[0xd801, 0xdc01],
|
||
|
|
[0xddff, 0xdfff],
|
||
|
|
[0xd821, 0x0000],
|
||
|
|
[0xd821, 0xd821, 0xdea0]
|
||
|
|
].forEach(function (bytes, index) {
|
||
|
|
const str = String.fromCharCode(...bytes)
|
||
|
|
const check = Buffer.from(str)
|
||
|
|
const buf = encode(str)
|
||
|
|
t.equal(buf.length, check.length)
|
||
|
|
t.equal(toHex(buf, 0, buf.length), check.toString('hex'), `#${index} [${bytes}].toHex() ... ${check.toString('hex')}`)
|
||
|
|
t.equal(decode(buf, 0, buf.length), check.toString(), `#${index} [${bytes}].toUtf8`)
|
||
|
|
})
|
||
|
|
t.end()
|
||
|
|
})
|
||
|
|
|
||
|
|
test('all code points', function (t) {
|
||
|
|
const blockSize = 2048
|
||
|
|
const blocks = 65536 / blockSize
|
||
|
|
let code = 0
|
||
|
|
for (let block = 0; block < blocks; block += 1) {
|
||
|
|
const expected = {}
|
||
|
|
const actual = {}
|
||
|
|
for (let i = 0; i < blockSize; i += 1, code += 1) {
|
||
|
|
const str = String.fromCharCode(code)
|
||
|
|
const buf = new Uint8Array(encodingLength(str))
|
||
|
|
encode(str, buf, 0)
|
||
|
|
const exp = Buffer.from(str)
|
||
|
|
expected[code] = exp.toString('hex')
|
||
|
|
actual[code] = toHex(buf, 0, buf.length)
|
||
|
|
}
|
||
|
|
t.same(actual, expected)
|
||
|
|
}
|
||
|
|
t.end()
|
||
|
|
})
|
||
|
|
|
||
|
|
test('performance', { skip: typeof TextDecoder === 'undefined' }, function (t) {
|
||
|
|
function run (impl) {
|
||
|
|
const start = Date.now()
|
||
|
|
for (let i = 0; i < 10000; i++) {
|
||
|
|
TEST_STRINGS.forEach(function (str) {
|
||
|
|
impl.encodingLength(str)
|
||
|
|
impl.decode(impl.encode(str))
|
||
|
|
})
|
||
|
|
}
|
||
|
|
return Date.now() - start
|
||
|
|
}
|
||
|
|
const encoder = new TextEncoder()
|
||
|
|
const decoder = new TextDecoder()
|
||
|
|
const native = {
|
||
|
|
encode (str, buf, offset) {
|
||
|
|
return encoder.encode(str)
|
||
|
|
},
|
||
|
|
decode (str) {
|
||
|
|
return decoder.decode(str)
|
||
|
|
},
|
||
|
|
encodingLength (str) {
|
||
|
|
return encoder.encode(str).length
|
||
|
|
}
|
||
|
|
}
|
||
|
|
TEST_STRINGS.forEach(function (str) {
|
||
|
|
const bytes = native.encode(str)
|
||
|
|
t.same(bytes, utf8Codec.encode(str))
|
||
|
|
t.same(native.decode(bytes), utf8Codec.decode(bytes))
|
||
|
|
t.same(native.encodingLength(str), utf8Codec.encodingLength(str))
|
||
|
|
})
|
||
|
|
const perf = {
|
||
|
|
native: run(native),
|
||
|
|
utf8: run(utf8Codec)
|
||
|
|
}
|
||
|
|
t.ok(perf.native > perf.utf8, `native(${perf.native}ms) > utf8-codec(${perf.utf8}ms)`)
|
||
|
|
t.end()
|
||
|
|
})
|