diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-13 21:34:48 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-13 21:34:48 -0800 |
| commit | 76cb9c2a39d477a64824a985ade40507e3bbade1 (patch) | |
| tree | 41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/@exodus/bytes/utf16.node.js | |
| parent | 819a39a21ac992b1393244a4c283bbb125208c69 (diff) | |
| download | neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2 neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip | |
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/@exodus/bytes/utf16.node.js')
| -rw-r--r-- | vanilla/node_modules/@exodus/bytes/utf16.node.js | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/vanilla/node_modules/@exodus/bytes/utf16.node.js b/vanilla/node_modules/@exodus/bytes/utf16.node.js new file mode 100644 index 0000000..53183a3 --- /dev/null +++ b/vanilla/node_modules/@exodus/bytes/utf16.node.js @@ -0,0 +1,70 @@ +import { assertU8, E_STRING, E_STRICT_UNICODE } from './fallback/_utils.js' +import { isDeno, isLE } from './fallback/platform.js' +import { E_STRICT, decodeApiDecoders } from './fallback/utf16.js' + +if (Buffer.TYPED_ARRAY_SUPPORT) throw new Error('Unexpected Buffer polyfill') + +const { isWellFormed, toWellFormed } = String.prototype +const to8 = (a) => new Uint8Array(a.buffer, a.byteOffset, a.byteLength) + +// Unlike utf8, operates on Uint16Arrays by default + +function encode(str, loose = false, format = 'uint16') { + if (typeof str !== 'string') throw new TypeError(E_STRING) + if (format !== 'uint16' && format !== 'uint8-le' && format !== 'uint8-be') { + throw new TypeError('Unknown format') + } + + if (loose) { + str = toWellFormed.call(str) // Buffer doesn't do this with utf16 encoding + } else if (!isWellFormed.call(str)) { + throw new TypeError(E_STRICT_UNICODE) + } + + const ble = Buffer.from(str, 'utf-16le') + + if (format === 'uint8-le') return to8(ble) + if (format === 'uint8-be') return to8(ble.swap16()) + if (format === 'uint16') { + const b = ble.byteOffset % 2 === 0 ? ble : Buffer.from(ble) // it should be already aligned, but just in case + if (!isLE) b.swap16() + return new Uint16Array(b.buffer, b.byteOffset, b.byteLength / 2) + } + + /* c8 ignore next */ + throw new Error('Unreachable') +} + +// Convert to Buffer view or a swapped Buffer copy +const swapped = (x, swap) => { + const b = Buffer.from(x.buffer, x.byteOffset, x.byteLength) + return swap ? Buffer.from(b).swap16() : b +} + +// We skip TextDecoder on Node.js, as it's is somewhy significantly slower than Buffer for utf16 +// Also, it incorrectly misses replacements with Node.js is built without ICU, we fix that +function decodeNode(input, loose = false, format = 'uint16') { + let ble + if (format === 'uint16') { + if (!(input instanceof Uint16Array)) throw new TypeError('Expected an Uint16Array') + ble = swapped(input, !isLE) + } else if (format === 'uint8-le' || format === 'uint8-be') { + assertU8(input) + if (input.byteLength % 2 !== 0) throw new TypeError('Expected even number of bytes') + ble = swapped(input, format === 'uint8-be') + } else { + throw new TypeError('Unknown format') + } + + const str = ble.ucs2Slice(0, ble.byteLength) + if (loose) return toWellFormed.call(str) + if (isWellFormed.call(str)) return str + throw new TypeError(E_STRICT) +} + +const decode = isDeno ? decodeApiDecoders : decodeNode + +export const utf16fromString = (str, format = 'uint16') => encode(str, false, format) +export const utf16fromStringLoose = (str, format = 'uint16') => encode(str, true, format) +export const utf16toString = (arr, format = 'uint16') => decode(arr, false, format) +export const utf16toStringLoose = (arr, format = 'uint16') => decode(arr, true, format) |
