Skip to content

Commit 99fa5c4

Browse files
committed
perf: no non-ascii strings in data
1 parent 8f46caa commit 99fa5c4

3 files changed

Lines changed: 67 additions & 50 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ If you don't need support for legacy multi-byte encodings, you can use the lite
6464
import { TextDecoder, TextEncoder } from '@exodus/bytes/encoding-lite.js'
6565
```
6666

67-
This reduces the bundle size 9x:\
68-
from 91 KiB gzipped for `@exodus/bytes/encoding.js` to 10 KiB gzipped for `@exodus/bytes/encoding-lite.js`.\
67+
This reduces the bundle size 10x:\
68+
from 90 KiB gzipped for `@exodus/bytes/encoding.js` to 9 KiB gzipped for `@exodus/bytes/encoding-lite.js`.\
6969
(For comparison, `text-encoding` module is 190 KiB gzipped, and `iconv-lite` is 194 KiB gzipped).
7070

7171
It still supports `utf-8`, `utf-16le`, `utf-16be` and all single-byte encodings specified by the spec,

fallback/single-byte.encodings.js

Lines changed: 54 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fallback/single-byte.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ export const assertEncoding = (encoding) => {
1313
function getEncoding(encoding) {
1414
assertEncoding(encoding)
1515
if (encoding === xUserDefined) {
16-
return Array.from({ length: 128 }, (_, i) => String.fromCharCode(0xf7_80 + i)).join('')
16+
return Array.from({ length: 128 }, (_, i) => 0xf7_80 + i)
1717
}
1818

19-
return encodings[encoding]
19+
let prev = 0
20+
return encodings[encoding].map((x) => (prev += x)) // eslint-disable-line no-return-assign
2021
}
2122

2223
const mappers = new Map()
@@ -28,13 +29,13 @@ export function encodingMapper(encoding) {
2829
const cached = mappers.get(encoding)
2930
if (cached) return cached
3031

31-
const incomplete = getEncoding(encoding).includes('\uFFFD')
32+
const codes = getEncoding(encoding)
33+
const incomplete = codes.includes(0xff_fd)
3234
let map
3335
const mapper = (arr, start = 0) => {
3436
if (!map) {
3537
map = Uint16Array.from({ length: 256 }, (_, i) => i) // Unicode subset
36-
const strings = getEncoding(encoding).split('')
37-
map.set(Uint16Array.from(strings.map((x) => x.charCodeAt(0))), 128)
38+
map.set(Uint16Array.from(codes), 128)
3839
}
3940

4041
const o = Uint16Array.from(start === 0 ? arr : arr.subarray(start)) // copy to modify in-place, also those are 16-bit now
@@ -63,12 +64,13 @@ export function encodingDecoder(encoding) {
6364
if (cached) return cached
6465

6566
let strings
66-
const incomplete = getEncoding(encoding).includes('\uFFFD')
67+
const codes = getEncoding(encoding)
68+
const incomplete = codes.includes(0xff_fd)
6769
const decoder = (arr, loose = false) => {
6870
if (!strings) {
69-
const part = getEncoding(encoding).split('')
70-
strings = Array.from({ length: 128 }, (_, i) => String.fromCharCode(i)).concat(part)
71-
while (strings.length < 256) strings.push(String.fromCharCode(strings.length))
71+
const allCodes = Array.from({ length: 128 }, (_, i) => i).concat(codes)
72+
while (allCodes.length < 256) allCodes.push(allCodes.length)
73+
strings = allCodes.map((c) => String.fromCharCode(c))
7274
}
7375

7476
const prefix = decodeLatin1(arr, 0, asciiPrefix(arr))

0 commit comments

Comments
 (0)