Skip to content

Commit 1126aec

Browse files
committed
perf: simplify latin1 on Node.js
Also improves Deno perf on it
1 parent 5365362 commit 1126aec

1 file changed

Lines changed: 18 additions & 12 deletions

File tree

single-byte.node.js

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { isDeno, isLE } from './fallback/platform.js'
44
import { asciiPrefix } from './fallback/latin1.js'
55
import { encodingMapper, encodingDecoder, encodeMap, E_STRICT } from './fallback/single-byte.js'
66

7+
const NON_LATIN = /[^\x00-\xFF]/ // eslint-disable-line no-control-regex
8+
79
function latin1Prefix(arr, start) {
810
let p = start | 0
911
const length = arr.length
@@ -21,8 +23,22 @@ function latin1Prefix(arr, start) {
2123
return length
2224
}
2325

26+
export function latin1toString(arr) {
27+
assertU8(arr)
28+
if (arr.byteLength === 0) return ''
29+
return toBuf(arr).latin1Slice() // .latin1Slice is faster than .asciiSlice
30+
}
31+
32+
export function latin1fromString(s) {
33+
if (typeof s !== 'string') throw new TypeError(E_STRING)
34+
if (NON_LATIN.test(s)) throw new TypeError(E_STRICT)
35+
const b = Buffer.from(s, 'latin1')
36+
return new Uint8Array(b.buffer, b.byteOffset, b.byteLength)
37+
}
38+
2439
export function createSinglebyteDecoder(encoding, loose = false) {
2540
if (typeof loose !== 'boolean') throw new TypeError('loose option should be boolean')
41+
if (encoding === 'iso-8859-1') return latin1toString
2642
if (isDeno) {
2743
const jsDecoder = encodingDecoder(encoding) // asserts
2844
return (arr) => {
@@ -33,13 +49,12 @@ export function createSinglebyteDecoder(encoding, loose = false) {
3349
}
3450
}
3551

36-
const isLatin1 = encoding === 'iso-8859-1'
3752
const latin1path = encoding === 'windows-1252'
3853
const { incomplete, mapper } = encodingMapper(encoding) // asserts
3954
return (arr) => {
4055
assertU8(arr)
4156
if (arr.byteLength === 0) return ''
42-
if (isLatin1 || isAscii(arr)) return toBuf(arr).latin1Slice() // .latin1Slice is faster than .asciiSlice
57+
if (isAscii(arr)) return toBuf(arr).latin1Slice() // .latin1Slice is faster than .asciiSlice
4358

4459
// Node.js TextDecoder is broken, so we can't use it. It's also slow anyway
4560

@@ -59,8 +74,6 @@ export function createSinglebyteDecoder(encoding, loose = false) {
5974
}
6075
}
6176

62-
const NON_LATIN = /[^\x00-\xFF]/ // eslint-disable-line no-control-regex
63-
6477
function encode(s, m) {
6578
const len = s.length
6679
let i = 0
@@ -90,16 +103,11 @@ function encode(s, m) {
90103
export function createSinglebyteEncoder(encoding, { mode = 'fatal' } = {}) {
91104
// TODO: replacement, truncate (replacement will need varying length)
92105
if (mode !== 'fatal') throw new Error('Unsupported mode')
106+
if (encoding === 'iso-8859-1') return latin1fromString
93107
const m = encodeMap(encoding) // asserts
94-
const isLatin1 = encoding === 'iso-8859-1'
95108

96109
return (s) => {
97110
if (typeof s !== 'string') throw new TypeError(E_STRING)
98-
if (isLatin1) {
99-
if (NON_LATIN.test(s)) throw new TypeError(E_STRICT)
100-
const b = Buffer.from(s, 'latin1')
101-
return new Uint8Array(b.buffer, b.byteOffset, b.byteLength)
102-
}
103111

104112
// Instead of an ASCII regex check, encode optimistically - this is faster
105113
// Check for 8-bit string with a regex though, this is instant on 8-bit strings so doesn't hurt the ASCII fast path
@@ -114,7 +122,5 @@ export function createSinglebyteEncoder(encoding, { mode = 'fatal' } = {}) {
114122
}
115123
}
116124

117-
export const latin1toString = /* @__PURE__ */ createSinglebyteDecoder('iso-8859-1')
118-
export const latin1fromString = /* @__PURE__ */ createSinglebyteEncoder('iso-8859-1')
119125
export const windows1252toString = /* @__PURE__ */ createSinglebyteDecoder('windows-1252')
120126
export const windows1252fromString = /* @__PURE__ */ createSinglebyteEncoder('windows-1252')

0 commit comments

Comments
 (0)