Skip to content

Commit 77fe45c

Browse files
committed
size: add utf16.browser impl
1 parent a28a587 commit 77fe45c

2 files changed

Lines changed: 51 additions & 0 deletions

File tree

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
"/single-byte.node.js",
125125
"/utf16.js",
126126
"/utf16.d.ts",
127+
"/utf16.browser.js",
127128
"/utf16.native.js",
128129
"/utf16.node.js",
129130
"/utf8.js",
@@ -205,6 +206,7 @@
205206
"types": "./utf16.d.ts",
206207
"node": "./utf16.node.js",
207208
"react-native": "./utf16.native.js",
209+
"browser": "./utf16.browser.js",
208210
"default": "./utf16.js"
209211
},
210212
"./utf8.js": {
@@ -222,6 +224,7 @@
222224
}
223225
},
224226
"browser": {
227+
"./utf16.js": "./utf16.browser.js",
225228
"./fallback/utf8.auto.js": "./fallback/utf8.auto.browser.js"
226229
},
227230
"react-native": {

utf16.browser.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// We trust browsers to always have correct TextDecoder / TextEncoder for UTF-16 with ignoreBOM without streaming
2+
3+
import { encode as encodeJS } from './fallback/utf16.js'
4+
import { isLE, E_STRING, E_STRICT_UNICODE } from './fallback/_utils.js'
5+
6+
const ignoreBOM = true
7+
const decoderFatalLE = new TextDecoder('utf-16le', { ignoreBOM, fatal: true })
8+
const decoderLooseLE = new TextDecoder('utf-16le', { ignoreBOM })
9+
const decoderFatalBE = new TextDecoder('utf-16be', { ignoreBOM, fatal: true })
10+
const decoderLooseBE = new TextDecoder('utf-16be', { ignoreBOM })
11+
const decoderFatal16 = isLE ? decoderFatalLE : decoderFatalBE
12+
const decoderLoose16 = isLE ? decoderLooseLE : decoderLooseBE
13+
const { isWellFormed } = String.prototype
14+
15+
function encode(str, loose, format) {
16+
if (typeof str !== 'string') throw new TypeError(E_STRING)
17+
if (format !== 'uint16' && format !== 'uint8-le' && format !== 'uint8-be') {
18+
throw new TypeError('Unknown format')
19+
}
20+
21+
if (!loose && isWellFormed && !isWellFormed.call(str)) throw new TypeError(E_STRICT_UNICODE)
22+
const shouldSwap = (isLE && format === 'uint8-be') || (!isLE && format === 'uint8-le')
23+
const u16 = encodeJS(str, loose, !loose && isWellFormed, shouldSwap)
24+
return format === 'uint16' ? u16 : new Uint8Array(u16.buffer, u16.byteOffset, u16.byteLength)
25+
}
26+
27+
function decode(input, loose, format) {
28+
switch (format) {
29+
case 'uint16':
30+
if (!(input instanceof Uint16Array)) throw new TypeError('Expected an Uint16Array')
31+
return loose ? decoderLoose16.decode(input) : decoderFatal16.decode(input)
32+
case 'uint8-le':
33+
if (!(input instanceof Uint8Array)) throw new TypeError('Expected an Uint8Array')
34+
if (input.byteLength % 2 !== 0) throw new TypeError('Expected even number of bytes')
35+
return loose ? decoderLooseLE.decode(input) : decoderFatalLE.decode(input)
36+
case 'uint8-be':
37+
if (!(input instanceof Uint8Array)) throw new TypeError('Expected an Uint8Array')
38+
if (input.byteLength % 2 !== 0) throw new TypeError('Expected even number of bytes')
39+
return loose ? decoderLooseBE.decode(input) : decoderFatalBE.decode(input)
40+
}
41+
42+
throw new TypeError('Unknown format')
43+
}
44+
45+
export const utf16fromString = (str, format = 'uint16') => encode(str, false, format)
46+
export const utf16fromStringLoose = (str, format = 'uint16') => encode(str, true, format)
47+
export const utf16toString = (arr, format = 'uint16') => decode(arr, false, format)
48+
export const utf16toStringLoose = (arr, format = 'uint16') => decode(arr, true, format)

0 commit comments

Comments
 (0)